This is really more a C pattern than a C++ pattern, isn't it?
Frustrated by C's limitations relative to Golang, last year I sketched out an approach to using X-macros to define VNC protocol message types as structs with automatically-generated serialization and deserialization code. So for example you would define the VNC KeyEvent message as follows:
And that would generate a KeyEvent typedef (to an anonymous struct type) and two functions named read_KeyEvent_big_endian and write_KeyEvent_big_endian. (It wouldn't be difficult to add debug_print_KeyEvent.) Since KeyEvent is a typedef, you can use it as a field type in other, larger structs just like u8 and u32.
Note that here there are two Xes, and they are passed as parameters to the KeyEvent_fields macro rather than being globally defined and undefined over time. To me this feels cleaner than the traditional way.
What I love are macros that take parameters that are the names of other macros to call, and parameters that are fragments of code without balanced brackets to insert.
The term of art for that and the X pattern kind of approach is "macrology".
An infamous example is Microsoft's original C preprocessor macros for generating COM components for C code.
MFC infamously used a similar approach for its COM/OLE bindings to C++ too. You could include the same interface definition .h files in either C or C++ code with the proper meta-macros defined to declare the same interfaces in either C or C++ code (which was kind of the whole point of COM).
That was long before the (in contrast) much more elegant ATL (ActiveX Template Library) implemented with C++ templates.
Microsoft isn't the only offender -- Sun did it to!
Check out the "arctochain.c" code in the original NeWS server by Vaughan Pratt and James Gosling for a great example of macros that take the names of other macros and code fragments containing gotos, to make a state machine with a twisty maze of hopping gotos, plus some manual exception handling gotology like "goto this_curve_is_trash;" and "goto straight;" thrown in for fun:
/*-
Convert a conic arc to a curve
arctochain.c, Tue Jun 11 14:23:17 1985
"Elegance and truth are inversely related." -- Becker's Razor
Vaughan Pratt
Sun Microsystems
This code is a version of the conix package that has been
heavily massaged by James Gosling.
*/
>[...] Two pieces of work were done at SUN which provide other key components of the solution to the imaging problems. One is Vaughan Pratt's Conix [53], a package for quickly manipulating curve bounded regions, and the other is Craig Taylor's Pixscene [63], a package for performing graphics operations in overlapped layers of bitmaps. [...]
>[...] Pixscene is based on a shape algebra package. The ability, provided by Conix, to do algebra very rapidly on curves should make non-rectangular windows perform well. [...]
>The main loop of the NeWS PostScript interpreter itself is the realization of Duff's dire warning "Actually, I have another revolting way to use switches to implement interrupt driven state machines but it's too horrid to go into."
#define case4(tag) case tag: case tag+1: case tag+2: case tag+3
#define case16(tag) case4(tag):case4(tag+4):case4(tag+8):case4(tag+12)
#define case32(tag) case16(tag):case16(tag+16)
> Does it build today
In this form it won't, since that is missing the Sun PixRect library. And you also need the "operators.h"
file (which is in another directory...) and the "acceptconnect" function.
On comp.windows.news Usenet group and on the NeWS book is reported that a portable codebase (called REF) exists, and Sun ported it on Ultrix (on thr VAXstation) and System V. I read it included a version of PixRect called "Generic PixRect", which should be more portable.
BitSavers put on the net a tape dump of X/NeWS 2.0, and there are some differences: a different graphics library called SHAPES replacing CScript (and it needs the Ace preprocessor to build the device dependent portion of the library), a different memory allocator, support for X11 protocol, support for Folio F3 fonts, and other things.
Fortunately I found a copy of PixRect in the leaked sources of SunOS 4.1.4 , but it's not enough, since that device dependent routines must be rewritten.
I'm slowly porting NeWS 1.1 to NetBSD (since that wscons is easier to work with) as a proof of concept. I managed to execute code and grt my screen turn blue, but the current obstacle is decoding binary fonts: the OG routines fail completely on 64 bit machines, since that the original format assumes 32 bit machine words and big endian order. More work will be needed.
Frustrated by C's limitations relative to Golang, last year I sketched out an approach to using X-macros to define VNC protocol message types as structs with automatically-generated serialization and deserialization code. So for example you would define the VNC KeyEvent message as follows:
And that would generate a KeyEvent typedef (to an anonymous struct type) and two functions named read_KeyEvent_big_endian and write_KeyEvent_big_endian. (It wouldn't be difficult to add debug_print_KeyEvent.) Since KeyEvent is a typedef, you can use it as a field type in other, larger structs just like u8 and u32.Note that here there are two Xes, and they are passed as parameters to the KeyEvent_fields macro rather than being globally defined and undefined over time. To me this feels cleaner than the traditional way.
The usage above is in http://canonical.org/~kragen/sw/dev3/binmsg_cpp.c, MESSAGE_TYPE and its ilk are in http://canonical.org/~kragen/sw/dev3/binmsg_cpp.h, and an alternative approach using Python instead of the C preprocessor to generate the required C is in http://canonical.org/~kragen/sw/dev3/binmsg.py.