Я сделал что-то похожее, чтобы встроить язык ассемблера для пользовательского формата байт-кода, используя некоторую магию макросов C99 и Perl.
Макросы
#define x3_pragma_(...) _Pragma(#__VA_ARGS__)
#define x3_asm(...) ((const struct x3instruction []){ \
x3_pragma_(X3 ASM __VA_ARGS__) \
})
преобразование
x3_asm(exit = find val(0))
в
((const struct x3instruction []){
#pragma X3 ASM exit = find val(0)
})
, который передается по сценарию Perl для получения
((const struct x3instruction []){
{ { { X3_OPFINDVAL, { .as_uint = (0) } }, { X3_OPEXIT, { 0 } } } },
})
Пример вызова gcc и perl будет выглядеть так:
gcc -E foo.c | perl x3pp.pl | gcc -o foo.o -x c -
Это сложнее, чем строго необходимо, но я счел полезным, чтобы препроцессор C запускался раньше моего пользовательского препроцессора, и мне также понравилось, что с помощью прагм источник остается допустимым C.