Well, yesterday I implemented the "#include" capability. It was actually very fun and instructive - it made me recall the "prepare to throw one away" phrase from "Mythical man month". Let me elaborate:
I had a gut feeling that there should be some simple, "enlightened" recursive solution for "#include", but nothing came to my head. So I intentionally started coding a prototype. It resulted in 2 functions, with quite a lot of duplicated code, but it worked. Using the experience from this prototype, I coded a single function, that was shorter than each of the previous ones and did all the job, in that "enlightened recursive" kind of way. Nice ! Indeed, sometimes it's best to code a working prototype to understand how things work. Note taken.
Then I started implementing the "#define...#ifdef..." family. Oh goodness... this is complicated, and I see no "enlightened" way to code it. I didn't finish, will take on it now again, hopefully I'll be over this until the evening. Here comes some rant:
Sometimes, it's just impossible to create a simple solution to something. The specs are so complicated with so many special cases and things that should go this and that way... I'm willing to challenge anyone, to code a CLEAN implementation of the #define...#ifdef...#else, etc. capability of the c-preprocessor. CLEAN means without tons of flags, and generally code that "looks right" rather than "tailored to somehow solve the problem".
I don't feel too bad about it though. It's because I've seen (and even modified) the code of two other, popular implementations of cpp:
- One from Decus, that ran on many IBM platforms: ugly spaghetti, written in old, K&R style C. Dozens of "goto"s and "break flags". Files named cpp1.c, cpp2.c ... cpp6.c (hail modularity !).
- Another from GNU itself. The cpp of gcc 2.96. To say it's much better than the one from Decus is a big lie. They implement a lame parser of C, with highly unstructured code, huge "switches" with a lot of flags.
Enough rant for today, back to work...