Re: Preprocessor-Direktiven im Inneren eines Makros
David Haller <[email protected]>
| Newsgroups | gmane.linux.suse.programming |
|---|---|
| Message-ID | <[email protected]> |
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 <linux/tty.h> bzw. <bits/ioctl-types.h>.
>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