[c++] What is the worst real-world macros/pre-processor abuse you've ever come across?

What is the worst real-world macros/pre-processor abuse you've ever come across (please no contrived IOCCC answers *haha*)?

Please add a short snippet or story if it is really entertaining. The goal is to teach something instead of always telling people "never use macros".


p.s.: I've used macros before... but usually I get rid of them eventually when I have a "real" solution (even if the real solution is inlined so it becomes similar to a macro).


Bonus: Give an example where the macro was really was better than a not-macro solution.

Related question: When are C++ macros beneficial?

This question is related to c++ c macros preprocessor

The answer is


A past employer found there were no implementations of BASIC-PLUS on modern Unix systems, so they tried to re-implement it using C pre-processor macros:

#define IF if(
#define THEN ) {
#define ENDIF }
#define GOTO goto L

...etc.

Horrific.


Have to do this from memory, but was about like this: Working with a lib for writing Symbian apps. Hidden in a header file you needed to include was this little gem:

// Here come the register defines:
#define C <something>
#define N <something>
<two more single letter defines>

In our code the loading of a file with a hardcoded filename failed. When we changed the file location from C to D drive, it magically worked...


The worst I've seen is in my current project where there are a whole lot of cases of:

#if PROGRAMA
     .
     .
    if(...)
    {
     .
     .
     .
#else
    .
     .
    if(...)
    {
     .
     .
     .
#endif
     }

Yeah, he closes 2 opens with a single close.


The worst I've ever encountered was in a product containing a suite of executables where the designated technical leader hadn't figured out libraries.

Instead, he had sets of files that were shared in several Visual Source Safe folders. He then realised they needed to behave slightly differently for each application.

There's a number of refactoring steps you could apply here.

Instead, he used #ifdefs

   void DisplayLoadError()
   {
   #if defined __TIMETABLE_EDITOR
   MessageBox("Timetable Editor failed to load the correct timetable", MB_ERROR);
   #else if defined __SCHEDULESET_EDITOR
   MessageBox("Schedule Set Editor faied to load the correct Schedule Set", MB_ERROR);
   #else if defined __ROSTER_EDITOR
   MessageBox("Roster Editor failed to load the correct Roster", MB_ERROR);
   #endif
   }

I once saw a macro package that would alias every C keyword to let you effectively program in Klingon. That's right, Klingon. (Un)fortunately, the project was abandoned and taken down several years ago.


I was bored one day and was playing around with blocks in Objective-C...

#define Lambda(var, body) [^ id(id (var)) { return (body);} copy]
#define Call(f, arg) ((id(^)(id))(f))(arg)
#define Int(num) [NSNumber numberWithInteger:(num)]
#define Mult(a, b) Int([(a) integerValue] * [(b) integerValue])
#define Add(a, b) Int([(a) integerValue] + [(b) integerValue])
#define Sub1(n) Int([(n) integerValue] - 1)
#define Add1(n) Int([(n) integerValue] + 1)
#define If(cond, thenblock, elseblock) ([(cond) integerValue] ? (thenblock) : (elseblock))
#define Cons(car, cdr_) [[ConsType alloc] initWithCar:(car) cdr:(cdr_)]
#define Car(list) [(list) car]
#define Cdr(list) [(list) cdr]
#define Define(var, value) id var = (value)
#define Nullq(value) Int(value == nil)

allowing "interesting" things like:

Define(Y, Lambda(f, Call(Lambda(x, Call(x, x)),
                         Lambda(x, Call(f, Lambda(y, Call(Call(x, x), y)))))));
Define(AlmostTotal, Lambda(f, Lambda(list, If(Nullq(list), Int(0),
                                              Add(Car(list), Call(f, Cdr(list)))))));
Define(Total, Call(Y, AlmostTotal));
Print(Call(Total, Cons(Int(4), Cons(Int(5), Cons(Int(8), nil)))));

(some function and class definitions not shown for sake of brevity)


At Lucent, I once took a look at the source code of Steve Bourne's original Unix shell, and found he'd used the C pre-processor to make C look like Pascal or Algol. The part dealing with if statements looked like this:

#define IF   if (
#define THEN ) {
#define ELSE } else {
#define ELIF } else if (
#define FI   ; }

A friend of mine told me he'd done some maintenance on it in the mid-1990s, and it was still the same. (There's a lesson here for us in the inherent conservatism of a code base.)

Of course Steve did this as an experiment in the early days, and I'm sure would have had second thoughts if he'd written it later.

Update: According to Wikipedia's Bourne Shell article, the macros gave it an Algol 68 flavor. And, the full set of macros is here! They apparently influenced the founders of the International Obfuscated C Code Contest.


The NFS code in BSD-kernels use goto between macros. It's still in use, and the code actually works. I know of several persons who have tried to clean it up, but all of them have given up after a while - it's just too messy.

You can see it here: http://www.openbsd.org/cgi-bin/cvsweb/src/sys/nfs/nfsm_subs.h?rev=1.43


At the time it seemed like a good idea to "pass" a macro as an argument into another macro. (I just couldn't stand the thought of defining a list of values in multiple places.) The code here is contrived (and not very motivating), but gives you the idea:

#define ENUM_COLORS(CallbackMacro) \
    CallbackMacro(RED)   \
    CallbackMacro(GREEN) \
    CallbackMacro(BLUE)  \
    // ...

#define DEFINE_COLOR_TYPE_CALLBACK(Color) \
    Color,

enum MyColorType {
    ENUM_COLORS(DEFINE_COLOR_TYPE_CALLBACK)
};

void RegisterAllKnownColors(void)
{
#define REGISTER_COLOR_CALLBACK(Color) \
    RegisterColor(Color, #Color);

    ENUM_COLORS(REGISTER_COLOR_CALLBACK)
}

void RegisterColor(MyColorType Color, char *ColorName)
{
    // ...
}

Anything that uses the Token concatenation operator ##. I've seen this used to hack together psudo-template systems in C++ and other horrible things. The worst thing about using it is how impossibly cryptic your error messages become.

I have seen one good use for it however. There was a macro #MONITOR_COMPONENT(classname) that generated classes at compile time that would inherit from a predefined monitor class and classname and that would autoregister with a singleton class that was used to monitor each component.

Did it work? Yes, was it the nicest way of doing it.. probably not.


I have used header files as big macros:

// compile-time-caller.h
#define param1 ...
#define param2 ...
#include "killer-header.h"

// killer-header.h
// uses param1 and param2

I have also created recursive header files.

// compile-time-caller.h
#define param1 ...
#define param2 ...
#include "killer-header.h"

// killer-header.h"
#if ... // conditional taking param1 and param2 as parameters
#define temp1 param1
#define temp2 param2
#define param1 ... // expression taking temp1 and temp2 as parameters
#define param2 ... // expression taking temp1 and temp2 as parameters
#include "killer-header.h"
// some actual code
#else
// more actual code
#endif

switch (device_id)
{
#ifndef PROD_1
#ifndef PROD_2
#ifdef PROD_3
  case ID_1:
#endif

#ifdef PROD_4

#ifdef PROD_5
  case ID_2:
  case ID_3:
  case ID_4:
#elif defined(PROD_4)
#ifndef PROD_6
  case ID_1:
#endif // PROD_6
  case ID_5:
#endif

  case ID_6:
#endif

#ifdef PROD_7
  #ifndef PROD_8
    case ID_7:
  #endif
#endif

(names changed to protect the not so innocent)

Notice that we haven't even gotten to any code yet, this is just to get to the first actual bit of code. This actually happens (in almost, but not exactly the same way) for several functions, each of which, in the end only have 4 possible variations (which are also mostly copy/paste with slight variations and #ifdefs of their own).


#undef near
#undef far

When I was new to game programming I was writing a frustum for a camera class is a game that I wrote, I had really strange errors in my code.

It turns out that Microsoft had some #defines for near and far in windows.h which caused my _near and _far variables to error on the lines that contained them. It was very difficult to track the problem down because (I was a newbie at the time) and they only existed on four lines in the whole project so i didn't realise right away.


#define private public

Be gentle, I wrote this as the only way I can think of to generically capture exceptions.

I use it to capture and stop exceptions from propagating out of my public interface functions...

/// Catch all generic exceptions and log appropriately.
/// Logger is insulated from throwing, so this is a NO THROW operation.
#define CatchAll( msg ) \
    catch( const Poco::Exception &e )   \
    {   \
        try{ LogCritical( Logs.System(), std::string( e.displayText() ).append( msg ) );}catch(...){assert(0);} \
    }   \
    catch( const std::exception &e )    \
    {   \
        try{LogCritical( Logs.System(), std::string( e.what() ).append( msg ) );}catch(...){assert(0);} \
    }   \
    catch(...)  \
    {   \
        try{ LogCritical( Logs.System(), std::string( "Exception caught in " __FUNCTION__ ". " ).append( msg ) );}catch(...){assert(0);}    \
    }   

I dislike the complexity and I hate macros, but how else would you "do" a generic catch handler? This isn't meant to be the end-all, this is just my generic catch handler to insulate legacy public functions and quickly add at least some level of protection when I know the function is getting invoked across a boundary which might throw up if a C++ exception were to be thrown (your welcome, JNI).

So does it make you run and hide, or is it the only way to do something like this?

Basically...

try{
// some block of code capable of throwing
}
CatchAll()

When I first came across macros in C they had me stumped for days. Below is what I was faced with. I imagine it makes perfect sense to C experts and is super efficient however for me to try and work out what exactly was going on meant cutting and pasting all the different macros together until the whole function could be viewed. Surely that's not good practice?! What's wrong with using a plain old function?!

#define AST_LIST_MOVE_CURRENT(newhead, field) do { \
typeof ((newhead)->first) __list_cur = __new_prev; \
AST_LIST_REMOVE_CURRENT(field); \
AST_LIST_INSERT_TAIL((newhead), __list_cur, field); \
} while (0) 

Raymond Chen has a really good rant against using flow control macros. His best example is straight from the original Bourne shell source code:

ADDRESS alloc(nbytes)
    POS     nbytes;
{
    REG POS rbytes = round(nbytes+BYTESPERWORD,BYTESPERWORD);

    LOOP    INT     c=0;
    REG BLKPTR  p = blokp;
    REG BLKPTR  q;
    REP IF !busy(p)
        THEN    WHILE !busy(q = p->word) DO p->word = q->word OD
        IF ADR(q)-ADR(p) >= rbytes
        THEN    blokp = BLK(ADR(p)+rbytes);
            IF q > blokp
            THEN    blokp->word = p->word;
            FI
            p->word=BLK(Rcheat(blokp)|BUSY);
            return(ADR(p+1));
        FI
        FI
        q = p; p = BLK(Rcheat(p->word)&~BUSY);
    PER p>q ORF (c++)==0 DONE
    addblok(rbytes);
    POOL
}

The worst one I saw was the non-use :-)

Someone wrote a strcpy (I think that was it... over 10 years ago now) function inside of a method (because they didn't want the overhead of calling strcpy... sigh).

They clued in that it wouldn't work for Japanese characters so they added an "if" at the start to do ASCII or Unicode. At that point the code was about a screen long... likely killing cache coherency and erasing his supposed savings for the inlining of the code.

The code was identical save for the types (so should have used a macro).

Of course the strcpy that they wrote was much much much slower than the hand tuned assembler one that was in the standard library...

Of course if they had just done it all as a macro it could have been replaced with a call to strcpy...

Of course I quit the company (not directly because of that...)


I once had to port a C application from unix to windows, the specific nature of which shall remain unnamed to protect the guilty. The guy who wrote it was a professor unaccustomed to writing production code, and had clearly come to C from some other language. It also happens that English wasn't his first language, though the country he came from the majority of people speak it quite well.

His application made heavy use of the preprocessor to twist the C language into a format he could better understand. But the macros he used the most were defined in a header file named 'Thing.h' (seriously), which included the following:

#define I  Any void_me
#define thou  Any void_thee
#define iam(klas)  klas me = (klas) void_me
#define thouart(klas)  klas thee = (klas) void_thee
#define my  me ->
#define thy  thee ->
#define his  him ->
#define our  my methods ->
#define your  thy methods ->

...which he then used to write monstrosities like the following:

void Thing_setName (I, const char *name) {
iam (Thing);
if (name != my name) {
    Melder_free (my name);
    my name = Melder_wcsdup (name);
    }
    our nameChanged (me);
}

void Thing_overrideClass (I, void *klas) {
iam (Thing);
my methods = (Thing_Table)klas;
if (! ((Thing_Table) klas) -> destroy)
    ((Thing_Table) klas) -> _initialize (klas);
}

The entire project (~60,000 LOC) was written in a similar style -- marco hell, weird names, Olde-English jargon, etc. Fortunately we were able to throw the code out since I found an OSS library which performed the same algorithm dozens of times faster.

(I've copied and edited this answer which I originally made on this question).


I like this example, it uses the macro to approximate the value of PI. The larger the circle, the more accurate the approximation.

#define _ -F<00||--F-OO--;
int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{
            _-_-_-_
       _-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
        _-_-_-_-_-_-_-_
            _-_-_-_
}

Another is the c program

c

To compile you need to define c as

-Dc="#include <stdio.h> int main() { char *t =\"Hello World\n\"; while(*t) putc(*t++, stdout); return 0; }"

My worst:

#define InterlockedIncrement(x) (x)++
#define InterlockedDecrement(x) (x)--

I spent two days of my life tracking down some multi-threaded COM ref-counting issue because some idiot put this in a header file. I won't mention the company I worked for at the time.

The moral of this story? If you don't understand something, read the documentation and learn about it. Don't just make it go away.


Any macro that uses the token concatenation operator ##.

I saw one that a colleague of mine had the pleasure of working with. They tried to make a custom-implementation of string interning, so they re-implemented strings using a massive number of macros that (of course) didn't work properly. Trying to figure out what it did made my eyes explode because of all the ##'s scattered about.


Try to debug big project that really loves macros, and there is a lot of macros that calls other macros that calls other macros etc etc. (5-10 levels of macros was not that uncommon)

And then top it up with a lot of #ifdef this macrot #else that macro, so if you follow the code it like a tree of different paths it can go.

The only solution is most cases was to precompile and read that instead....


A mix between Pascal syntax and french keywords:

#define debut {
#define fin }
#define si if(
#define alors ){
#define sinon }else{
#define finsi }

I'm adding another one that has started to annoy me over time:

#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0]))

And that's if they get it right; I've seen versions with all possible permutations of parenthesis present or not. I've seen it defined twice in the same header file.

Mainly my argument applies to Windows (though I assume other OS SDKs have something similar), where just about everyone seems to feel the need to define this macro in their project's header, and I don't understand why.

WinNT.h (which is included by Windows.h) defines a very nice version that does some template voodoo to cause compile time errors if you pass a pointer type instead of an array.

Of course it falls back to exactly what I wrote above if you are building a C program, but I would still not redefine something the SDK has by default for no reason.


By a classmate who failed to understand the rules about magic numbers:
#define TWO_HUNDRED_AND_EIGHTY_THREE_POINT_ONE 283.1


See this answer re how a dyslexic colleague made life easier for themselves with a common header file full of things like #define fasle false.


I maintain code that has gotos in macros. So a function will have a label at the end but no visible goto in the function code. To make matters worse the macro is at the end of other statements usually off the screen unless you scroll horizontally.

#define CHECK_ERROR if (!SomeCondition) goto Cleanup

void SomeFunction() 
{ 
    SomeLongFunctionName(ParamOne, ParamTwo, ParamThree, ParamFour); CHECK_ERROR  
    //SomeOtherCode  
    Cleanup:    
   //Cleanup code  
}

#define PROCESS_AND_RETURN(X) \
X.process(); \
// Important: Return only after invoking virtual method process() \
return X

Due to "Important" comment, the macro never returns the object and CRASH!


Coroutines (AKA Stackless threads) in C. :) It's Evil trickery.

#define crBegin static int state=0; switch(state) { case 0:
#define crReturn(i,x) do { state=i; return x; case i:; } while (0)
#define crFinish }
int function(void) {
    static int i;
    crBegin;
    for (i = 0; i < 10; i++)
        crReturn(1, i);
    crFinish;
}

int decompressor(void) {
    static int c, len;
    crBegin;
    while (1) {
        c = getchar();
        if (c == EOF)
            break;
        if (c == 0xFF) {
            len = getchar();
            c = getchar();
            while (len--)
            crReturn(c);
        } else
        crReturn(c);
    }
    crReturn(EOF);
    crFinish;
}


void parser(int c) {
    crBegin;
    while (1) {
        /* first char already in c */
        if (c == EOF)
            break;
        if (isalpha(c)) {
            do {
                add_to_token(c);
        crReturn( );
            } while (isalpha(c));
            got_token(WORD);
        }
        add_to_token(c);
        got_token(PUNCT);
    crReturn( );
    }
    crFinish;
}

I found it in libtidy,:

 /* Internal symbols are prefixed to avoid clashes with other libraries */
 #define TYDYAPPEND(str1,str2) str1##str2
 #define TY_(str) TYDYAPPEND(prvTidy,str)

 TY_(DocParseStream)(bar,foo);

The problem is that visual studio 2005 and maybe other ide go to definition and go to declaration features only find the #define TY_(...) and not the desired DocParseStream declaration.

Maybe it is safer this way.

I think they should put a prefix for each function and not call a macro to do the job.. it's cluttering the code.. but maybe I am wrong about that. What do you think..?

Ps: It seems that almost all the internal function const and others are prefixed using this.. My colleague just told me that it is usual.. wtf? Maybe I missed something.


#define return if (std::random(1000) < 2) throw std::exception(); else return

this is just so evil. It's random, which means it fires in different places all the time, it changes return statement, which usually have some code on it that could fail all by itself, it changes innocent looking keyword that you won't ever get suspicious over and it uses exception from std space so you won't try to search through your sources to find it's source. Just brilliant.


I agree that for the most part, macros are horrible to use, but i have found a few instances where they have been useful.

This one is actually brilliant IMHO, as you can only get something similar with sprintf, which then requires resource allocations and whatnot, plus, all work is done entirely by the preprocessor

// Macro: Stringize
//
//      Converts the parameter into a string
//
#define Stringize( L )          #L


// Macro: MakeString
//
//      Converts the contents of a macro into a string
//
#define MakeString( L )     Stringize(L)


// Macro: $LINE
//
//      Gets the line number as a string
//
#define $LINE                   MakeString( __LINE__ )


// Macro: $FILE_POS
//
//      Gets the current file name and current line number in a format the Visual Studio
//      can interpret and output goto
//
// NOTE: For VS to properly interpret this, it must be at the start of the line (can only have whitespace before)
//
#define $FILE_POS               __FILE__ "(" $LINE ") : "

The other that I loathe to use, but find it extremely useful is doing something like this, which basically allows me to quickly generate templates that have a variable number of template parameters

#define TEMPLATE_DEFS    typename ReturnType
#define TEMPLATE_DECL   ReturnType
#define FUNCTION_PARAMS void
#define FUNCTION_PASS   
#define GENERIC_CALLBACK_DECL_NAME      CallbackSafePointer0
#include "Callback.inl"

#define TEMPLATE_DEFS   typename ReturnType, typename P1
#define TEMPLATE_DECL   ReturnType, P1
#define FUNCTION_PARAMS P1 param1
#define FUNCTION_PASS   param1
#define GENERIC_CALLBACK_DECL_NAME      CallbackSafePointer1
#include "Callback.inl"

#define TEMPLATE_DEFS   typename ReturnType, typename P1, typename P2
#define TEMPLATE_DECL   ReturnType, P1, P2
#define FUNCTION_PARAMS P1 param1, P2 param2
#define FUNCTION_PASS   param1, param2
#define GENERIC_CALLBACK_DECL_NAME      CallbackSafePointer2
#include "Callback.inl"

#define TEMPLATE_DEFS   typename ReturnType, typename P1, typename P2, typename P3
#define TEMPLATE_DECL   ReturnType, P1, P2, P3
#define FUNCTION_PARAMS P1 param1, P2 param2, P3 param3
#define FUNCTION_PASS   param1, param2, param3
#define GENERIC_CALLBACK_DECL_NAME      CallbackSafePointer3
#include "Callback.inl"

// and so on...

Although this makes it kind of horrible to read "Callback.inl", it does completely eliminate rewriting the same code with a different number of arguments. I should also mention that "Callback.inl" #undefs all of the macros at the end of the file, hence, the macros themselves won't interfere with any other code, it just makes "Callback.inl" a little harder to write (reading and debuging isn't too hard though)


#define interface struct

in some of Optima++ headers (Optima++ is/was a Watcom/Powersoft IDE I had to work with).


I'm not fond of the Boost Preprocessor stuff. I attempted once to figure out how to use it (we had Boost in the project anyway...), but as near as I could tell, using it would make my error messages SO unreadable that it wasn't worth it.

I liked the idea of the equivalent of looping macros, but it was just too much.


An 'architect', very humble guy, you know the type, had the following:

#define retrun return

because he liked to type fast. The brain-surgeon used to like to shout at people who were smarter than him (which was pretty much everyone), and threaten to use his black-belt on them.


Another piece of 'creative' use of the preprocessor, though it is more in the terminology employed than in the mechanics (which are incredibly mundane):

/***********************************************************************
 * OS2 and PCDOS share a lot of common codes.  However, sometimes
 * OS2 needs codes similar to those of UNIX.  NOTPCDOS is used in these
 * situations
 */

#ifdef OS2
#define PCDOS
#define NOTPCDOS
#else /* OS2 */
#ifndef PCDOS
#define NOTPCDOS
#endif /* PCDOS */
#endif /* OS2 */

Genuine code - I thought I'd removed it, but apparently not. I must have done so out in some temporary branch and not gotten permission to check it back into the main code. One more item for the 'to do' list.


The worst abuses (and I'm guilty of doing this occasionally) is using the preprocessor as some sort of data file replacement, ie:

#define FOO_RELATION \  
BAR_TUPLE( A, B, C) \  
BAR_TUPLE( X, Y, Z) \ 

and then somewhere else:

#define BAR_TUPLE( p1, p2, p3) if( p1 ) p2 = p3;
FOO_RELATION
#undef BAR_TUPLE

which will result in:

if( A ) B = C;
if( X ) Y = Z;

This pattern can be used to do all sorts of (terrible) stuff... generate switch statements or huge if else blocks, or interface with "real" code. You could even use it to ::cough:: generate a context menu in a non-oo context menu system ::cough::. Not that I'd ever do anything so lame.

Edit: fixed mismatched parenthesis and expanded example


In one year of the International Obfuscated C Coding Contest, there was an entry where the entire program was:

P

With the proviso that you could define P in the makefile to be whatever program you wanted.

As I recall, it won in one of the categories, and the next year a rule had popped up disallowing that style of entry.

(Edit: six months later or something... I'm sure the "No IOCCC" thing wasn't in the main question when I wrote this...)


#define TRUE 0 // dumbass

The person who did this explained himself some years later - most (if not all) C library functions return 0 as an indication that everything went well. So, he wanted to be able to write code like:

if (memcpy(buffer, packet, BUFFER_SIZE) == TRUE) {
; // rape that packet
}

Needless to say, nobody in our team (tester or developer) ever dared to glance at his code again.


Found in declarations, to much confusion:

NON_ZERO_BYTE         Fixed(8)  Constant('79'X),

Found later:

IF WORK_AREA(INDEX) = ZERO_BYTE THEN  /* found zero byte */ 
   WORK_AREA(INDEX) = NON_ZERO_BYTE ; /* reset to nonzero*/

I would like to submit for the contest a gem called chaos-pp, which implements a functional language by means of the preprocessor macros.

One of the examples is calculating the 500th fibonacci number entirely by the preprocessor:

The original code before preprocessor looks as this:

int main(void) {
   printf
     ("The 500th Fibonacci number is "
      ORDER_PP(8stringize(8to_lit(8fib(8nat(5,0,0)))))
      ".\n");
   return 0;
}

preprocessing the file we get the following result (after a rather long wait):

$ cpp -I../inc fibonacci.c 2>/dev/null | tail
  return fib_iter(n, 0, 1);
}
# 63 "fibonacci.c"
int main(void) {
   printf
     ("The 500th Fibonacci number is "
      "139423224561697880139724382870407283950070256587697307264108962948325571622863290691557658876222521294125"
      ".\n");
   return 0;
}

#include <iostream>
#define public_static_void_main(x) int main()
#define System_out_println(x) std::cout << x << std::endl

public_static_void_main(String[] args) {
  System_out_println("Hello World!");
}

I once put together this horrifying C++ code which used macros to help hook functions into the import table of DLLs.


#define ARGLIST(...) __VA_ARGS__

#define CPPTYPELESSARG(typelessParams) thisptr, typelessParams
#define CPPTYPEDARG(typedParams) void* thisptr, typedParams
#define CPPTYPELESSNOARG thisptr
#define CPPTYPEDNOARG void* thisptr

#define CPPHOOKBODY(hookName, params) void *thisptr; \
    __asm { mov thisptr, ecx } \
    return On##hookName ( params );


#define CHOOKBODY(hookName, typelessParams) return On##hookName( typelessParams );

#define CPPHOOK(InjectHookRef, importLib, importFunc, hookName, returnType, typedParams, typelessParams) \
    HOOKIMPL(InjectHookRef, importLib, importFunc, hookName, returnType, CPPTYPEDARG(typedParams), typelessParams, \
    typedParams, __thiscall, __stdcall, CPPHOOKBODY(hookName, CPPTYPELESSARG(typelessParams)))

#define CPPHOOKNOARG(InjectHookRef, importLib, importFunc, hookName, returnType, typedParams, typelessParams) \
    HOOKIMPL(InjectHookRef, importLib, importFunc, hookName, returnType, CPPTYPEDNOARG, typelessParams, \
    typedParams, __thiscall, __stdcall, CPPHOOKBODY(hookName, CPPTYPELESSNOARG))

#define CDECLHOOK(InjectHookRef, importLib, importFunc, hookName, returnType, typedParams, typelessParams) \
    HOOKIMPL(InjectHookRef, importLib, importFunc, hookName, returnType, typedParams, typelessParams, \
    typedParams, __cdecl, __cdecl, CHOOKBODY(hookName, typelessParams))

#define CDECLFUNC(name, address, returnType, args) \
    typedef returnType (__cdecl *name##Ptr)(args); \
    name##Ptr name = (name##Ptr) address;

#define CPPFUNC(name, address, returnType, args) \
    typedef returnType (__thiscall *name##Ptr)(void* thisptr, args); \
    name##Ptr name = (name##Ptr) address;

#define STDFUNC(name, address, returnType, args) \
    typedef returnType (__stdcall *name##Ptr)(args); \
    name##Ptr name = (name##Ptr) address;

#define STDHOOK(InjectHookRef, importLib, importFunc, hookName, returnType, typedParams, typelessParams) \
    HOOKIMPL(InjectHookRef, importLib, importFunc, hookName, returnType, typedParams, typelessParams, \
    typedParams, __stdcall, __stdcall, CHOOKBODY(hookName, ARGLIST(typelessParams)))

#define HOOKIMPL(InjectHookRef, importLib, importFunc, hookName, returnType, typedParams, typelessParams, hookParams, fnPtrCall, hookCall, hookBody) \
        typedef returnType (fnPtrCall *##hookName##OrigPtr )( typedParams ); \
        class hookName : public IHook \
        { \
        public: \
            typedef hookName##OrigPtr func_type; \
        private: \
            static void* m_origFunction; \
            static bool m_bModifyImport; \
            static std::string m_lib; \
            static std::string m_importFunc; \
            static std::string m_sHookName; \
            static returnType hookCall hookName##FnHook ( hookParams ) \
            { \
                hookBody \
            } \
            static bool ImplIsModifyImport() { return hookName::m_bModifyImport; } \
            static void ImplSetModifyImport(bool bModify) { hookName::m_bModifyImport = bModify; } \
            static const std::string& ImplGetLibName() { return hookName::m_lib; } \
            static const std::string& ImplGetImportFunctionName() { return hookName::m_importFunc; } \
            static void ImplSetOriginalAddress(void* fn) { hookName::m_origFunction = fn; } \
            static void* ImplGetOriginalAddress() { return hookName::m_origFunction; } \
            static returnType On##hookName ( typedParams ); \
            static void* ImplGetNewAddress() { return hookName::##hookName##FnHook; } \
            static const std::string& ImplGetHookName() { return hookName::m_sHookName; } \
        public: \
            hookName() \
            { \
                InjectHookRef.AddHook((IHook*)this); \
                hookName::m_lib = importLib; \
                hookName::m_importFunc = importFunc; \
                hookName::m_sHookName = #hookName; \
                hookName::m_origFunction = NULL; \
                hookName::m_bModifyImport = true; \
            } \
            virtual bool IsModifyImport() const { return hookName::ImplIsModifyImport(); } \
            virtual void SetModifyImport(bool bModify) { hookName::ImplSetModifyImport(bModify); } \
            virtual const std::string& GetHookName() const { return hookName::ImplGetHookName(); } \
            virtual const std::string& GetLibName() const { return hookName::ImplGetLibName(); } \
            virtual const std::string& GetImportFunctionName() const { return hookName::ImplGetImportFunctionName(); } \
            virtual void* GetOriginalAddress() const { return hookName::ImplGetOriginalAddress(); } \
            virtual void* GetNewAddress() const { return hookName::ImplGetNewAddress(); } \
            virtual void SetOriginalAddress(void* fn) { hookName::m_origFunction = fn; } \
            static func_type GetTypedOriginalAddress() { return reinterpret_cast(hookName::m_origFunction); } \
        }; \
        void* hookName::m_origFunction = NULL; \
        bool hookName::m_bModifyImport = false; \
        std::string hookName::m_lib; \
        std::string hookName::m_importFunc; \
        std::string hookName::m_sHookName; \
        static hookName g##hookName##Inst;

Which in turn allowed me to do this:

CPPHOOK(gIH, "SimEngine.dll", "?AddEntity@Player@@UAEXPAVEntity@@@Z", PlayerAddEntity, void, void* ent, ent);

/* Called when the engine calls Player::AddEntity(entity) */ void PlayerAddEntity::OnPlayerAddEntity(void *thisptr, void *ent) { unsigned int id = getPlayerID(thisptr);

gIH.GetLog()->Info("Player %d adding entity %s.", 
    getPlayerID(thisptr), getEntityName(ent));

gPlayers[id] = thisptr;

/*if( id == 2 && gPlayers[1] && gPlayers[2] )
    EntitySetOwner::GetTypedOriginalAddress() (ent, gPlayers[1]);*/
//gEnts[ent] = Entity(ent, Vector3f());

PlayerAddEntity::GetTypedOriginalAddress() (thisptr, ent);

}


A coworker and I found these two gems in some of our code for object streaming. These macros were instantiated in EVERY SINGLE class file that did streaming. Not only is this hideous code spewed all over our code base, when we approached the original author about it, he wrote a 7 page article on our internal wiki defending this as the only possible way to accomplish what he was attempting to do here.

Needless to say, it has since been refactored out and is no longer used in our code base.

Don't be thrown off by the highlighted keywords. This is ALL a macro

#define DECLARE_MODIFICATION_REQUEST_PACKET( T )                                                \
namespace NameSpace                                                                     \
{                                                                                       \
                                                                                        \
class T##ElementModificationRequestPacket;                                                          \
}                                                                                       \
                                                                                        \
DECLARE_STREAMING_TEMPLATES( IMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::ElementModificationRequestPacket<T>, OtherNameSpace::NetPacketBase )    \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( NameSpace::ElementModificationRequestPacket<T> )     \
DECLARE_AUTOGENERATION_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::T##ModificationRequestPacket, NameSpace::ElementModificationRequestPacket<T> )      \
                                                                                        \
namespace NameSpace {                                                                   \
class DLLIMPEXP_COMMON T##ModificationRequestPacket : public ElementModificationRequestPacket<T>\
{                                                                                       \
public:                                                                                 \
    T##ModificationRequestPacket( NetBase * pParent )                                   \
    : ElementModificationRequestPacket<T>( pParent ), m_Gen() {}                            \
                                                                                        \
    T##ModificationRequestPacket( NetBase * pParent,                                    \
                            Action          eAction,                                    \
                            const T &   rT )                                            \
    : ElementModificationRequestPacket<T>( pParent, eAction, rT ), m_Gen() {}               \
                                                                                        \
    T##ModificationRequestPacket( const T##ModificationRequestPacket & rhs )                        \
    : ElementModificationRequestPacket<T>( rhs ), m_Gen() {}                                \
                                                                                        \
    virtual                     ~T##ModificationRequestPacket( void ) {}                        \
                                                                                        \
    virtual Uint32          GetPacketTypeID( void ) const                           \
    {                                                                                   \
        return Net::T##_Modification_REQUEST_PACKET;                                        \
    }                                                                                   \
                                                                                        \
    virtual OtherNameSpace::ClassID GetClassID ( void ) const                           \
    {                                                                                   \
        return OtherNameSpace::NetBase::GenerateHeader( OtherNameSpace::ID__LICENSING,  \
                                                         Net::T##_Modification_REQUEST_PACKET );    \
    }                                                                                   \
                                                                                        \
    virtual T##ModificationRequestPacket * Create( void ) const                             \
    { return new T##ModificationRequestPacket( m_pParent ); }                                   \
                                                                                        \
    T##ModificationRequestPacket() {}                                                           \
                                                                                        \
protected:                                                                              \
    OtherNameSpace::ObjectAutogeneration<T##ModificationRequestPacket> m_Gen;                       \
                                                                                        \
    friend class OtherNameSpace::StreamingBase::StreamingClassInfoT<T##ModificationRequestPacket >;                     \
    OtherNameSpace::StreamingBase::Streaming<T##ModificationRequestPacket, ElementModificationRequestPacket<T> >    m_Stream;   \
                                                                                        \
};                                                                                      \
}                                                                                       \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::ListenerBase<const NameSpace::T##ModificationRequestPacket> )            \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::BroadcasterT<const NameSpace::T##ModificationRequestPacket> )            \
typedef  ThirdNameSpace::BroadcasterT<const T##ModificationRequestPacket>  T##ModifiedBroadcaster;



#define IMPLEMENT_MODIFICATION_REQUEST_PACKET( T )                                                                  \
DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( NameSpace::ElementModificationRequestPacket<T> )                         \
DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( ThirdNameSpace::ListenerBase<const NameSpace::T##ModificationRequestPacket> )        \
DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( ThirdNameSpace::BroadcasterT<const NameSpace::T##ModificationRequestPacket> )        \
INSTANTIATE_STREAMING_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE, NameSpace::ElementModificationRequestPacket<T>, OtherNameSpace::NetPacketBase ) \
INSTANTIATE_AUTOGENERATION_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE, NameSpace::T##ModificationRequestPacket, NameSpace::ElementModificationRequestPacket<T> )

Update (December 17, 2009):

More good news regarding this hideous macro author. As of August, the employee responsible for this monstrosity was sacked.


#define if while

It was joke played on someone, it wasn't found amusing by those affected


I did the following myself, and I think I learned something from it.

In 1992 or so I wrote a small Lisp interpreter. It wasn't implemented in normal C, but in an interpreted C-like language. This C-like language used the standard C pre-processor, though.

The Lisp interpreter of course contained the functions car, which is used in Lisp to return the first element in a list, and cdr, which returns the rest of the list. They were implemented like this:

LISPID car(LISPID id) {
    CHECK_CONS("car", 1, id);
    return cons_cars[id - CONS_OFFSET];
} /* car */

LISPID cdr(LISPID id) {
    CHECK_CONS("cdr", 1, id);
    return cons_cdrs[id - CONS_OFFSET];
} /* cdr */

(Data were stored in arrays, since there were no structs. CONS_OFFSET is the constant 1000.)

car and cdr are used frequently in Lisp, and are short, and since function calls weren't very fast in the implementation language, I optimized my code by implementing those two Lisp functions as macros:

#define car(id) (CHECK_CONS("car", 1, (id)), cons_cars[(id) - CONS_OFFSET])
#define cdr(id) (CHECK_CONS("car", 1, (id)), cons_cdrs[(id) - CONS_OFFSET])

CHECK_CONS checks that its argument actually is a list, and since that one is also used frequently in the interpreter, and is short, I wrote that one too as a macro:

#define CHECK_CONS(fun, pos, arg)   \
    (!IS_CONS(arg) ?        \
        LISP_ERROR("Arg " + pos + " to " + fun +    \
                   " must be a list: " + lispid2string(arg)) : 0)

IS_CONS and LISP_ERROR were also used frequently, so I made them into macros too:

#define IS_CONS(id) \
    (   intp(id) && (id) >= CONS_OFFSET     \
     && ((id) - CONS_OFFSET) < sizeof(cons_cars))

#define LISP_ERROR(str)     (throw((str) + "\n"))

Seems reasonable?

But then, why did the entire system crash on this line:

id2 = car(car(car(car((id1))));

I worked a long time to find the problem, until I finally checked what that short line was expanded to by the pre-processor. It was expanded to a 31370-character line, which I have here split into lines (502 of them) for clarity:

id2 = ((!(intp( (((!(intp( (((!(intp( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
&& ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000]))) && ( (((!(intp(
(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000]))) >= 1000 && ((
(((!(intp( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000]))) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (((!(intp( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1))
&& ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars))

AI Game Programming Wisdom has a chapter where macros were used to create a scripting language for finite state machines.

Since the book and code are copyrighted material, here's a Google book link to the page detailing the macros (The resulting script language can be found on page 324.)


Directly from Qt:

#define slots   /* */
#define signals /* */

Really nice to interact with other libs as boost::signals... Just an example, there are many others in Qt that create funny looking code like:

class X : public QObject {
   Q_OBJECT
private slots:
   //...
public signals:
   //...
};

And that is C++... but suddenly:

boost::signals::trackable

Is not valid C++ any more.


Anything using sendmail and its magic configuration syntax


#define protected private

Seemed like a good idea sometimes, but if you need to, you should probably just string replace anyway. Protected is fairly evil, allowing internal access to descendants isn't much better than just making the items public...


The driver code for an ASIC I used about 10 years ago had a lot of sections that looked like:

int foo(state_t *state) {
    int a, b, rval;

    $
    if (state->thing == whatever) {
        $
        do_whatever(state);
    }
    // more code

    $
    return rval;
}

After a lot of head scratching we finally found the definition:

#if DEBUG
#define $ dolog("%s %d", __FILE__, __LINE__);
#else
#define $
#endif

This was hard to find, because none of the source files that used it had any include files. There was a file called top.c source file that looked like:

#include <namechanged.h>
#include <foo.c>
#include <bar.c>
#include <baz.c>

Sure enough, this was the only file referenced in the Makefile. Whenever you changed anything, you had to recompile everything. This was "to make the code faster".


#define ever (;;)
for ever { 
   ...
}

Real-world? MSVC has macros in minmax.h, called max and min, which cause a compiler error every time I intend to use the standard std::numeric_limits<T>::max() function.


A "technical manager" who had formerly been a coder introduced the following wonderful macros into our C++ project because he thought that checking for NULL values in DOM parsing routines was just too much work:

TRYSEGV
CATCHSEGV

Under the covers, these used setjmp, longjmp, and a signal handler for SIGSEGV to emulate the ability to "catch" a segfault.

Of course, nothing in the code reset the jump pointed once the code had exited the scope of the original TRYSEGV macro invocation, so any segfault in the code would return to the (now invalid) jump_env pointer.

The code would immediately die there, but not before destroying the program stack and rendering debugging more or less pointless.


The obligatory

#define FOR  for

and

#define ONE  1
#define TWO  2
...

Who knew?


Good macros: (although personally I dislike the double parentheses required to use this syntax; I prefer either vararg macros (C99 only) or something like PRINTF_0, PRINTF_1, etc, depending on the number of arguments)

#ifdef DEBUG
#define PRINTF(x) printf x
#else
#define PRINTF(x)
#endif

Reduces code size / execution time (the first more than the second) for non-debug build; also prevents leaking debug text strings which may pose a smallish security risk


Related to Raymond's rant is the following horrible (in my opinion, of course) macro:

#define CALL_AND_CHECK(func, arg) \
    int result = func(arg);       \
    if(0 != result)               \
    {                             \
        sys.exit(-1);             \
    }                             \

I was pretty new to the practice of using macros and used this macro, but I expected the function that I passed to it to fail. And I was doing it in a background thread, so it stumped me for days why my entire app was "crashing".

As an aside, if only std::tr1::function was around when this macro was written, I would have a week of my life back!


It's not a C macro but...

Many years ago I had the fun task of porting the original Transport Tycoon from the PC to the Mac. The PC version was written entirely in assembler so we had to go through the whole source code and port it to 'PC' C code first and then port that to the Mac. Most of the code was OK, even object orientated in places. However, the world rendering system was unbelievable. For anyone who's not played the game, the world can be viewed at one of three zoom levels. The code for this was something along the lines of:

macro DrawMacro <list of arguments>
   a couple of thousand lines of assembler with loads of conditionals
   based on the macro arguments

DrawZoomLevel1:
   DrawMacro <list of magic numbers>

DrawZoomLevel2:
   DrawMacro <list of more magic numbers>

DrawZoomLevel3:
   DrawMacro <list of even more magic numbers>

We must have been using a slightly older version of MASM as the macro would crash the assembler when we tried to assemble it.

Skizz


#include <iostream>
#define System S s;s
#define public
#define static
#define void int
#define main(x) main()
struct F{void println(char* s){std::cout << s << std::endl;}};
struct S{F out;};

public static void main(String[] args) {
  System.out.println("Hello World!");
}

Challenge: Can anyone do it with fewer defines and structs? ;-)


ASA - http://www.ingber.com/#ASA

You really have to download it to appreciate it. The entire work flow is determined by macros. It is completely unreadable. As an example -

 if (asa_open == FALSE) {
asa_open = TRUE;
++number_asa_open;
#if ASA_PRINT
if (number_asa_open == 1) {
  /* open the output file */
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
#if ASA_SAVE
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
#else
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "w");
#endif
  }
#else /* USER_ASA_OUT */
  if (!strcmp (ASA_OUT, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
#if ASA_SAVE
    ptr_asa_out = fopen (ASA_OUT, "a");
#else
    ptr_asa_out = fopen (ASA_OUT, "w");
#endif
  }
#endif /* USER_ASA_OUT */
} else {
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
  }
#else
  if (!strcmp (ASA_OUT, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (ASA_OUT, "a");
  }
#endif
  fprintf (ptr_asa_out, "\n\n\t\t number_asa_open = %d\n",
           number_asa_open);
}
#endif /* ASA_PRINT */
} else {
++recursive_asa_open;
#if ASA_PRINT
if (recursive_asa_open == 1) {
  /* open the output file */
#if ASA_SAVE
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
  }
#else
  if (!strcmp (ASA_OUT, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (ASA_OUT, "a");
  }
#endif
#else /* ASA_SAVE */
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {

etc., etc.

And that is just setting up the options. the entire program is like that.


One fairly bad example:

#ifdef __cplusplus
#define class _vclass
#endif

This allows a C structure that contains a member variable called class to be handled by a C++ compiler. There are two headers with this construct in it; one of them also contains '#undef class' at the end and the other doesn't.


#define unless(cond) if(!cond)
#define until(cond) while(!cond)

Used:

unless( ptr == NULL) 
    ptr->foo();

Windows.h has a lot of functions that abused macros.


MrValdez is annoyed by the GetObject macro found in Windows.h

The GetObject macro changes the GetObject() function into GetObjectA() or GetObjectW() (depending if the build is compiled in non-unicode and unicode, respectively)

MrValdez hates having to do before the GetObject function line

#undef GetObject

Object *GetObject()

The alternative is to change the function name to something else like GetGameObject()


jdkoftinoff in the comments have nailed it: The problem is that all windows API functions are macros.

Adam Rosenfield mentioned that that the issues can be fixed by defining NOGDI, WIN32_LEAN_AND_MEAN, NOMINMAX, etc before including windows.h to remove the issues.


The hideous:

#define begin {
#define end }
/* and so on */

Seriously, if you want to code in Pascal, buy a Pascal compiler, don't destroy the beautiful C language.


#define FLASE FALSE

The programmer was a bad typist, and this was his most common mistake.


#define "CR_LF" '\r'

That confused the hell out of me for a while!


This is taken from a popular open source program. In fact it makes some parts of the code more readable by hiding the ugly legacy.

#define EP_STATUS    CASTLING][(BOARD_FILES-2)
#define HOLDINGS_SET CASTLING][(BOARD_FILES-1)

I guess there is nothing really bad here, I just find it funny.

http://git.savannah.gnu.org/cgit/xboard.git/tree/common.h


The use of the LINE preprocessor to generate unique ID for messages passed over the network:

NetworkMessages.h

#define MSG_LOGIN  __LINE__
#define MSG_LOGOUT __LINE__
#define MSG_CHAT   __LINE__

This is an example where the macro really was better than a non-macro solution:

In a non-macro solution classes, functions and variables have to be built to keep track of what ID the message is. The developer may or may not make the message ID tracking complicated whereas this is easier to read and debug.

In addition, its easier to add new messages just by adding the message into the source.

The disadvantage of this situation is that the file has to be included in all code that uses messages. Compile time would increase whenever a message is edited.


Examples related to c++

Method Call Chaining; returning a pointer vs a reference? How can I tell if an algorithm is efficient? Difference between opening a file in binary vs text How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Install Qt on Ubuntu #include errors detected in vscode Cannot open include file: 'stdio.h' - Visual Studio Community 2017 - C++ Error How to fix the error "Windows SDK version 8.1" was not found? Visual Studio 2017 errors on standard headers How do I check if a Key is pressed on C++

Examples related to c

conflicting types for 'outchar' Can't compile C program on a Mac after upgrade to Mojave Program to find largest and second largest number in array Prime numbers between 1 to 100 in C Programming Language In c, in bool, true == 1 and false == 0? How I can print to stderr in C? Visual Studio Code includePath "error: assignment to expression with array type error" when I assign a struct field (C) Compiling an application for use in highly radioactive environments How can you print multiple variables inside a string using printf?

Examples related to macros

How to use __DATE__ and __TIME__ predefined macros in as two integers, then stringify? how to use #ifdef with an OR condition? What is ":-!!" in C code? How to pass macro definition from "make" command line arguments (-D) to C source code? __FILE__ macro shows full path Where are the recorded macros stored in Notepad++? How to identify platform/compiler from preprocessor macros? What does "#pragma comment" mean? C Macro definition to determine big endian or little endian machine? How do I show the value of a #define at compile-time?

Examples related to preprocessor

#ifdef replacement in the Swift language How to determine whether code is running in DEBUG / RELEASE build? How to convert an enum type variable to a string? "Debug only" code that should run only when "turned on" Can gcc output C code after preprocessing? #if DEBUG vs. Conditional("DEBUG") #define in Java What is the worst real-world macros/pre-processor abuse you've ever come across?