Preprocessor-Direktiven im Inneren eines Makros
Ich würde gerne ein Makro bauen, das TABLE_ENTRY(FOO) zu #ifdef N_FOO { "FOO", N_FOO }, #endif expandiert - also einen Tabelleneintrag generiert, falls das Preprocessor-Symbol N_xyz definiert ist. Ziel ist, dass ich nachher im Programm schreiben kann: static const struct { const char *s; int v; } table[] = { TABLE_ENTRY(FOO) TABLE_ENTRY(BAR) TABLE_ENTRY(BAZ) TABLE_ENTRY(TOTO) TABLE_ENTRY(TITI) TABLE_ENTRY(TATA) }; und table[] dann genau die Einträge enthält, für die der entsprechende Wert auch definiert ist. Die Expansion TABLE_ENTRY(FOO) => { "FOO", N_FOO }, ist ja kein Problem, aber die Abfrage, ob N_FOO definiert ist, also das #ifdef - #endif außenrum, will nicht klappen. Wenn ich so etwas wie #define TABLE_ENTRY(x) \ #ifdef N_##x \ { #x, N_##x }, \ #endif versuche, beschwert sich CPP: t.c:2:3: error: '#' is not followed by a macro parameter Ideen? TIA T. -- Tilman Schmidt Phoenix Software GmbH Bonn, Germany --------------------------------------------------------------------- To unsubscribe, e-mail: opensuse-programming-de+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-programming-de+help@opensuse.org
Hello, On Tue, 29 Jul 2008, Tilman Schmidt wrote:
Ich würde gerne ein Makro bauen, das
TABLE_ENTRY(FOO)
zu
#ifdef N_FOO { "FOO", N_FOO }, #endif
expandiert - also einen Tabelleneintrag generiert, falls das Preprocessor-Symbol N_xyz definiert ist. Ziel ist, dass ich nachher im Programm schreiben kann:
static const struct { const char *s; int v; } table[] = { TABLE_ENTRY(FOO) TABLE_ENTRY(BAR) TABLE_ENTRY(BAZ) TABLE_ENTRY(TOTO) TABLE_ENTRY(TITI) TABLE_ENTRY(TATA) };
und table[] dann genau die Einträge enthält, für die der entsprechende Wert auch definiert ist.
Die Expansion TABLE_ENTRY(FOO) => { "FOO", N_FOO }, ist ja kein Problem, aber die Abfrage, ob N_FOO definiert ist, also das #ifdef - #endif außenrum, will nicht klappen. Wenn ich so etwas wie
#define TABLE_ENTRY(x) \ #ifdef N_##x \ { #x, N_##x }, \ #endif
versuche, beschwert sich CPP:
t.c:2:3: error: '#' is not followed by a macro parameter
Ideen?
Mehrstufig. Erklären kann ich jetzt grad nicht *gähn*: ==== t.c ==== #define N_FOO 1 #define N_BAZ 4 #ifdef N_FOO #define _TABLE_ENTRY_FOO { "FOO", N_FOO }, #else #define _TABLE_ENTRY_FOO #endif #ifdef N_BAR #define _TABLE_ENTRY_BAR { "BAR", N_BAR }, #else #define _TABLE_ENTRY_BAR #endif #ifdef N_BAZ #define _TABLE_ENTRY_BAZ { "BAZ", N_BAZ }, #else #define _TABLE_ENTRY_BAZ #endif #define TABLE_ENTRY(x) _TABLE_ENTRY_ ## x static const struct { const char *s; int v; } table[] = { TABLE_ENTRY(FOO) TABLE_ENTRY(BAR) TABLE_ENTRY(BAZ) { NULL, 0 } }; ==== $ cpp t.c | sed '/^$/d' # 1 "t.c" static const struct { const char *s; int v; } table[] = { { "FOO", 1 }, { "BAZ", 4 }, { NULL, 0 } }; Das sollte doch sein, was du suchst, odr? Evtl. könnte man, je nach dem was die Expansion der Makros sein soll, weiter makroisieren... -dnh -- Life is full of small and large disappointments, and then you die. -- M. Andrews --------------------------------------------------------------------- To unsubscribe, e-mail: opensuse-programming-de+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-programming-de+help@opensuse.org
Hi, Am 30.07.2008 08:05 schrieb David Haller:
Mehrstufig. Erklären kann ich jetzt grad nicht *gähn*:
==== t.c ==== #define N_FOO 1 #define N_BAZ 4
#ifdef N_FOO #define _TABLE_ENTRY_FOO { "FOO", N_FOO }, #else #define _TABLE_ENTRY_FOO #endif #ifdef N_BAR #define _TABLE_ENTRY_BAR { "BAR", N_BAR }, #else #define _TABLE_ENTRY_BAR #endif #ifdef N_BAZ #define _TABLE_ENTRY_BAZ { "BAZ", N_BAZ }, #else #define _TABLE_ENTRY_BAZ #endif
#define TABLE_ENTRY(x) _TABLE_ENTRY_ ## x
static const struct { const char *s; int v; } table[] = { TABLE_ENTRY(FOO) TABLE_ENTRY(BAR) TABLE_ENTRY(BAZ) { NULL, 0 } }; ====
$ cpp t.c | sed '/^$/d' # 1 "t.c" static const struct { const char *s; int v; } table[] = { { "FOO", 1 },
{ "BAZ", 4 }, { NULL, 0 } };
Das sollte doch sein, was du suchst, odr?
Nicht ganz. Was ich suche, ist eine leichter handhabbare Alternative zu #ifdef N_FOO { "FOO", N_FOO }, #endif #ifdef N_BAR { "BAR", N_BAR }, #endif #ifdef N_BAZ { "BAZ", N_BAZ }, #endif Deine Version ist da eher noch mühsamer zu schreiben.
Evtl. könnte man, je nach dem was die Expansion der Makros sein soll, weiter makroisieren...
Anwendung ist eine Übersetzungstabelle String <-> numerischer Wert für
die Liste der Line Disciplines in
Hello, On Fri, 01 Aug 2008, Tilman Schmidt wrote:
Am 30.07.2008 08:05 schrieb David Haller:
Mehrstufig. Erklären kann ich jetzt grad nicht *gähn*:
==== t.c ==== #define N_FOO 1 #define N_BAZ 4
#ifdef N_FOO #define _TABLE_ENTRY_FOO { "FOO", N_FOO }, #else #define _TABLE_ENTRY_FOO #endif #ifdef N_BAR #define _TABLE_ENTRY_BAR { "BAR", N_BAR }, #else #define _TABLE_ENTRY_BAR #endif #ifdef N_BAZ #define _TABLE_ENTRY_BAZ { "BAZ", N_BAZ }, #else #define _TABLE_ENTRY_BAZ #endif
#define TABLE_ENTRY(x) _TABLE_ENTRY_ ## x
static const struct { const char *s; int v; } table[] = { TABLE_ENTRY(FOO) TABLE_ENTRY(BAR) TABLE_ENTRY(BAZ) { NULL, 0 } }; ====
$ cpp t.c | sed '/^$/d' # 1 "t.c" static const struct { const char *s; int v; } table[] = { { "FOO", 1 },
{ "BAZ", 4 }, { NULL, 0 } };
Das sollte doch sein, was du suchst, odr?
Nicht ganz. Was ich suche, ist eine leichter handhabbare Alternative zu
#ifdef N_FOO { "FOO", N_FOO }, #endif #ifdef N_BAR { "BAR", N_BAR }, #endif #ifdef N_BAZ { "BAZ", N_BAZ }, #endif
Deine Version ist da eher noch mühsamer zu schreiben.
Evtl. könnte man, je nach dem was die Expansion der Makros sein soll, weiter makroisieren...
Anwendung ist eine Übersetzungstabelle String <-> numerischer Wert für die Liste der Line Disciplines in
bzw. . Die konkrete Menge der definierten Line Disciplines kann zwischen verschiedenen Systemen variieren. Im Programm würde ich gerne einfach die gemeinsame Obermenge aller Systeme eintragen, und bei der Kompilierung sollen dann die jeweils nicht definierten einfach weggelassen werden.
Du bekommst mit dem C-Präprozessor AFAIK kein '#ifdef' in ein Makro. Du kannst aber einen anderen Makroprozessor (m4) z.B. nehmen, oder die Makros schlicht generieren lassen, z.B. auch aus nem 'Makefile' heraus: ==== DISCP_HEADER := /usr/include/bits/ioctl-types.h KNOWN_DISCP := $(shell awk '/N_/{print $$2;}' $(DISCP_HEADER)) tableentries.h: for d in $(KNOWN_DISCP); do\ echo -e "#ifdef $$d\n#define { \"$${d/N_/}\", $$d },\n#endif\n";\ done > $@ foo.c: tableentries.h ==== Oder so. Du mußt dann nur noch an der passenden Stelle (von foo.c) in der Definition des 'struct' die generierte Headerdatei per #include einbinden. Oder das 'struct' mit in tableentries.h ausgeben (wäre wohl vorzuziehen). Das mit dem Header (ioctl-types.h) usw. bzw. welche N_* bekannt sind, mußt du halt anpassen. HTH, -dnh -- "I have a very firm grasp on reality! I can reach out and strangle it any time!" -- from the BSD fortune file --------------------------------------------------------------------- To unsubscribe, e-mail: opensuse-programming-de+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-programming-de+help@opensuse.org
On Sat, 2 Aug 2008 02:45:52 +0200, David Haller wrote:
Du bekommst mit dem C-Präprozessor AFAIK kein '#ifdef' in ein Makro.
Richtig, das ist nicht möglich. Philipp --------------------------------------------------------------------- To unsubscribe, e-mail: opensuse-programming-de+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-programming-de+help@opensuse.org
Am 02.08.2008 02:45 schrieb David Haller:
Du bekommst mit dem C-Präprozessor AFAIK kein '#ifdef' in ein Makro.
Ok. Schade.
Du kannst aber einen anderen Makroprozessor (m4) z.B. nehmen, oder die Makros schlicht generieren lassen, z.B. auch aus nem 'Makefile' heraus:
Danke, ich werde mal in die Richtung weiterdenken. -- Tilman Schmidt Phoenix Software GmbH Bonn, Germany
participants (3)
-
David Haller
-
Philipp Thomas
-
Tilman Schmidt