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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.