Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Stringify a list?

53 views
Skip to first unread message

Christian Gollwitzer

unread,
Apr 8, 2016, 7:24:30 AM4/8/16
to
Hello,

is it possible to stringify a list of arguments in a preprocessor macro?

Background: I'm interfacing with a C library, which expects two parallel
arrays, one with C strings, one with function pointers. I'd like to be
able to pass only a the list of functions to the macro. So I'd like to have

TABLE(add, subtract, multiply)

generate this code

const char * text[] = { "add", "subtract", "multiply", NULL };
void * fun[] = { add, subtract, multiply };


Christian

Ondra Holub

unread,
Apr 8, 2016, 12:23:03 PM4/8/16
to
Something like that:

#define ITEMS ITEM(add), ITEM(sub), ITEM(mul), ITEM(div)

#define ITEM ITEM_AS_STRING
const char* text[] = { ITEMS, NULL };
#undef I

#define I ITEM_AS_IS
void* fun[] = { ITEMS };
#undef I

Yes, it is ugly. You can move some stuff to included file, so it would look like:

#define ITEMS ITEM(add), ITEM(sub), ITEM(mul), ITEM(div)
#include "generate"

Which is "a bit" better.

Anyway, I would suggest to use one array of struct:

#define ITEM(item) { #item, item }

struct XY
{
const char* text;
void* fun;
}
xy[] =
{
ITEM(add),
ITEM(sub),
ITEM(mul),
ITEM(div)
};

Marcel Mueller

unread,
Apr 8, 2016, 12:26:20 PM4/8/16
to
On 08.04.16 13.24, Christian Gollwitzer wrote:
> Background: I'm interfacing with a C library, which expects two parallel
> arrays, one with C strings, one with function pointers. I'd like to be
> able to pass only a the list of functions to the macro. So I'd like to have
>
> TABLE(add, subtract, multiply)
>
> generate this code
>
> const char * text[] = { "add", "subtract", "multiply", NULL };
> void * fun[] = { add, subtract, multiply };

#define TABLE(p1, p2, p3) \
const char* text[] = { #p1, #p2, #p3 }; \
void* fun[] = { p1, p2, p3 }


Alf P. Steinbach

unread,
Apr 8, 2016, 12:28:57 PM4/8/16
to
You can start by defining

TABLE( ... ) \
const char* text[] = { FUNC_NAME_LIST( __VA_ARGS__ ) nullptr }; \
Func_type fun[] = { __VA_ARGS__ };

Now the problem is reduced to defining FUNC_NAME_LIST.

:)


All approaches I've seen are based on counting the number of macro
arguments, which can be done using a technique posted in comp.std.c
(IIRC) around 1999. That number can then be concatenated with a macro
name. Which can be a general macro that lets you invoke a specified
macro for each argument.

However, eespecially the Visual C++ compiler is problematic, because it
has its own ideas about how preprocessor symbol concatenation should work.

I think the Boost Preprocessor library supplies this functionality in a
portable way, as a macro FOR_EACH or similarly named, with workarounds
for various compilers.


Cheers & hth.,

- Alf

Melzzzzz

unread,
Apr 8, 2016, 3:11:23 PM4/8/16
to
Try D. It is easy in D....

Christian Gollwitzer

unread,
Apr 8, 2016, 3:46:14 PM4/8/16
to
Am 08.04.16 um 13:24 schrieb Christian Gollwitzer:
> is it possible to stringify a list of arguments in a preprocessor macro?
>

Thanks to all for your ideas. Indeed Boost does have a solution,
unfortunately with an ugly call syntax. Finally I found a small library
via stackoverflow. It's here:

https://github.com/swansontec/map-macro

Short & sweet :)

It's really a shame that preprocessor is such a crippled language.


Christian

Robbie Hatley

unread,
Apr 11, 2016, 1:17:33 AM4/11/16
to
Easy as pie.

Save the following to file called "table-macro-test.cpp":

#define TABLE(X,Y,Z) \
const char * text[] = { #X, #Y, #Z, NULL }; \
void * fun[] = { add, subtract, multiply };

TABLE ( add , subtract , multiply )

Then run that through the preprocessor:


%cpp table-macro-test.cpp
# 1 "table-macro-test.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "table-macro-test.cpp"
const char * text[] = { "add", "subtract", "multiply", NULL };
void * fun[] = { add, subtract, multiply };


Voila.


--
Cheers,
Robbie Hatley
Midway City, CA, USA
perl -le 'print "\154o\156e\167o\154f\100w\145ll\56c\157m"'
http://www.well.com/user/lonewolf/
https://www.facebook.com/robbie.hatley

Christian Gollwitzer

unread,
Apr 11, 2016, 2:28:30 AM4/11/16
to
Am 11.04.16 um 07:17 schrieb Robbie Hatley:
>
> On 4/8/2016 4:24 AM, Christian Gollwitzer wrote:
>
>> is it possible to stringify a list of arguments in a preprocessor macro?
>>
>> Background: I'm interfacing with a C library, which expects two
>> parallel arrays, one with C strings, one with function pointers.
>> I'd like to be able to pass only a the list of functions to the macro.
>> So I'd like to have
>>
>> TABLE(add, subtract, multiply)
>>
>> generate this code
>>
>> const char * text[] = { "add", "subtract", "multiply", NULL };
>> void * fun[] = { add, subtract, multiply };
>
> Easy as pie.
>
> Save the following to file called "table-macro-test.cpp":
>
> #define TABLE(X,Y,Z) \
> const char * text[] = { #X, #Y, #Z, NULL }; \
> void * fun[] = { add, subtract, multiply };
>
> TABLE ( add , subtract , multiply )

Thanks for your answer. This works for exactly three arguments. I want
to use the macro several times with a varying number of arguments. The
rest of the macro is also larger and generates a function. Fortunately,
I found a solution:

This macro:

https://github.com/swansontec/map-macro

can perform a maplike operation over a list of up to 360 arguments.

I needed to enhance it to pass an extra argument to the "lambda"-macro,
which turned out to be easy:

https://github.com/auriocus/AsynCA/blob/master/generic/map.h

Best regards,

Christian

0 new messages