什么是你遇到过的最糟糕的现实世界的macros/预处理器的滥用?
什么是最糟糕的 现实世界的macros/预处理器滥用你曾经遇到(请不要做作的IOCCC答案*哈哈*)?
请添加一个简短的片段或故事,如果它真的很有趣。 目标是教一些东西,而不是总是告诉人们“不要使用macros”。
ps:我之前使用过macros,但是通常当我有一个“真正的”解决scheme(即使真正的解决scheme是内联的,所以它变得类似于一个macros)我最终摆脱它们。
奖金:给出一个例子,其中macros观确实比非macros观解决scheme更好。
相关问题: 什么时候C ++macros有益?
从记忆来看,它看起来像这样:
#define RETURN(result) return (result);} int myfunction1(args) { int x = 0; // do something RETURN(x) int myfunction2(args) { int y = 0; // do something RETURN(y) int myfunction3(args) { int z = 0; // do something RETURN(z)
是的,没有任何function的花括号。 语法高亮是一团糟,所以他用vi编辑(不是vim,它有语法着色!)
他是一位俄语程序员,主要从事汇编语言工作。 他热衷于节省尽可能多的字节,因为他曾经在内存非常有限的系统上工作。 “这是卫星,只有很less的字节,所以我们用每个字节来做很多事情。” (位摆弄,重复使用机器指令字节的数值)当我试图找出什么types的卫星时,我只能得到“轨道卫星,为了进入轨道”。
他还有另外两个怪癖:一个凸镜安装在显示器上方,“知道谁在看”,偶尔突然从椅子上退出,做了十次俯卧撑。 他解释这最后一个是“编译器在代码中发现错误,这是惩罚”。
我最糟糕的:
#define InterlockedIncrement(x) (x)++ #define InterlockedDecrement(x) (x)--
我花了两天的时间跟踪一些multithreading的COM ref-counting问题,因为有些白痴把它放在头文件中。 我不会提到我当时工作的公司。
这个故事的寓意是什么? 如果你不明白,请阅读文档并了解它。 不要让它消失。
#define ever (;;) for ever { ... }
#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!"); }
挑战:任何人都可以用更less的定义和结构来做到这一点吗? 😉
#define private public
#define if while
这是一个笑话在某人身上发挥,没有被发现有趣的受害者
丑陋的:
#define begin { #define end } /* and so on */
说真的,如果你想在Pascal中编码,买一个Pascal编译器,不要破坏美丽的C语言。
一个“build筑师”,非常谦虚的人,你知道这个types,有以下几点:
#define retrun return
因为他喜欢打字快。 脑外科医生过去喜欢向那些比他更聪明的人大喊(这几乎是每个人),并威胁要用他们的黑带。
真实世界? MSVC在minmax.h中有macros,称为max
和min
,每当我打算使用标准std::numeric_limits<T>::max()
函数时,会导致编译器错误。
Pascal语法和法语关键字之间的混合:
#define debut { #define fin } #define si if( #define alors ){ #define sinon }else{ #define finsi }
Raymond Chen 对使用stream量控制macros有一个很好的咆哮 。 他最好的例子是直接从原始的Bourne shell源代码:
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 }
我想提交一个叫做chaos-pp的gem,它通过预处理macros实现一个函数式语言。
其中一个例子是完全由预处理器计算第500个斐波纳契数:
预处理器之前的原始代码如下所示:
int main(void) { printf ("The 500th Fibonacci number is " ORDER_PP(8stringize(8to_lit(8fib(8nat(5,0,0))))) ".\n"); return 0; }
预处理文件,我们得到以下结果(经过相当长的等待):
$ 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; }
直接从Qt:
#define slots /* */ #define signals /* */
真的很高兴与其他库交互作为boost :: signals …只是一个例子,在Qt中还有很多其他的创build有趣的代码,如:
class X : public QObject { Q_OBJECT private slots: //... public signals: //... };
那就是C ++ …但突然间:
boost::signals::trackable
不再有效的C ++。
Windows.h有很多滥用macros的函数。
MrValdez被Windows.h中的GetObjectmacros所困扰
GetObjectmacros将GetObject()函数更改为GetObjectA()或GetObjectW()(取决于构build是否分别以非unicode和unicode编译)
MrValdez讨厌在GetObject函数之前做的事情
#undef GetObject Object *GetObject()
另一种方法是将函数名称更改为GetGameObject()
评论中的jdkoftinoff已经指出:问题是所有的Windows API函数都是macros。
Adam Rosenfield提到,在包含windows.h之前,通过定义NOGDI,WIN32_LEAN_AND_MEAN,NOMINMAX等来解决问题是可以解决的。
#define return if (std::random(1000) < 2) throw std::exception(); else return
这是如此邪恶。 它是随机的,这意味着它始终在不同的地方启动,它改变了返回语句,它通常有一些代码可以自行失败,它改变了无辜的关键字,你永远不会怀疑,它使用来自标准空间的例外,所以你不会尝试search你的资源来find它的来源。 太棒了。
一位同事和我在我们的一些代码中发现了这两个gem用于对象stream式传输。 这些macros被实例化在每个单stream类文件,做stream。 这个可怕的代码不仅遍布我们的代码库,当我们接近原作者的时候,他在我们的内部wiki上写了一篇7页的文章,捍卫这个代码是完成他在这里尝试完成的唯一可能的方式。
不用说,它已经被重构,不再被用在我们的代码库中。
不要被突出显示的关键字抛弃。 这是一个macros
#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> )
更新(2009年12月17日):
关于这个丑陋的macros观作者更多的好消息。 截至8月,负责这个怪物的雇员被解雇。
我自己做了以下,我想我从中学到了一些东西。
在1992年左右,我写了一个小的Lisp翻译。 它不是在普通的C语言中实现的,而是以解释的类C语言来实现的。 不过,这种C语言使用标准的C预处理器。
Lisp解释器当然包含函数car ,它在Lisp中用来返回列表中的第一个元素,而cdr则返回列表的其余部分。 他们是这样实现的:
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 */
(数据存储在数组中,因为没有结构, CONS_OFFSET是常量1000.)
car和cdr经常在Lisp中使用,并且很短,而且由于函数调用在实现语言中不是很快,所以我通过将这两个Lisp函数实现为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检查它的参数实际上是一个列表,因为那个在解释器中也经常被使用,并且简短,所以我把它写成一个macros:
#define CHECK_CONS(fun, pos, arg) \ (!IS_CONS(arg) ? \ LISP_ERROR("Arg " + pos + " to " + fun + \ " must be a list: " + lispid2string(arg)) : 0)
IS_CONS和LISP_ERROR也经常使用,所以我也把它们变成macros:
#define IS_CONS(id) \ ( intp(id) && (id) >= CONS_OFFSET \ && ((id) - CONS_OFFSET) < sizeof(cons_cars)) #define LISP_ERROR(str) (throw((str) + "\n"))
似乎合理?
但是,那么为什么整个系统会崩溃呢?
id2 = car(car(car(car((id1))));
我花了很长时间才find问题,直到我终于看到预处理器扩展到的那一行。 它被扩展为一个31370字符的行,为了清楚起见,我在这里将它分成了几行(其中502行)
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))
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 ).
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 }
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.
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.
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…)
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)
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…)
The obligatory
#define FOR for
和
#define ONE 1 #define TWO 2 ...
Who knew?
#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.
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 }
#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!"); }
By a classmate who failed to understand the rules about magic numbers:
#define TWO_HUNDRED_AND_EIGHTY_THREE_POINT_ONE 283.1
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 {
等等
And that is just setting up the options. the entire program is like that.