What this program does ---------------------- This program is an implementation of an algorithm that calculates the date of the Sunday following the first full moon after the spring equinoxe. (Also known as "Easter", defined this way by the Nicaean Concilium in 325 Anno Domini.) The algorithm is attributed to the famous mathematician Carl Friedrich Gauss ["Meyers Handbuch ueber das Weltall", Meyer, 5th Edition, 1973, p149] and is suitable for anni domini within the Gregorian Calendar, that is, from 1582 AD to 2199 AD: Let J be the year. If J is from 1582 to 1699, let M be 22, let N be 2 If J is from 1700 to 1799, let M be 23, let N be 3 If J is from 1800 to 1899, let M be 23, let N be 4 If J is from 1900 to 2099, let M be 24, let N be 5 If J is from 2100 to 2199, let M be 24, let N be 6 Let a be the modulus of J divided by 19 Let b be the modulus of J divided by 4 Let c be the modulus of J divided by 7 Let d be the modulus of (19a + M) divided by 30 Let e be the modulus of (2b + 4c + 6d + N) divided by 7 The interesting Sunday is either March 22 + d + e or April d + e - 9 (only one of them is a valid date) with the following exceptions: April 26 must always be changed to April 19 April 25 must be changed to April 18 if d is 28 and a greater than 10 Example: J = 1962, M = 24, N = 5 a = J % 19 = 5 b = J % 4 = 2 c = J % 7 = 2 d = 119 % 30 = 29 e = 191 % 7 = 2 March 53 is invalid, so the result is April 22 1962 Why I think this is obfuscated ------------------------------ Apart from the calculation of the Easter date, the definition *and* calculation of which are obfuscations in their own right, obfuscation lurks in many places. Look at those macro identifiers. What can be more obvious than a program that explicitly mentions the grammatical constructs it is composed of? If you look at K&RII A.9.3 you will find that a compound statement consists of an opening brace followed by a declaration list followed by a semicolon followed by a statement list followed by another semicolon and a closing brace. Nobody can learn that by heart so I gently remind the reader by defining a macro that expresses this clearly (line 25). This goes up to the definition of a translation unit. Unfortunately, due to the IOCCC's size restrictions, I had to abbreviate some syntactic elements. "ae" actually reads "assignment expression". I had to stop at some arbitrary point, so don't waste your time trying to find out how preprocessing tokens form type qualifier lists, cast expressions or direct abstract declarators. Assuming the reader knows about these easy to remember language elements is justified in my opinion. The moral: Try to be as precise as can be and no one will comprehend what you mean. The formula: comprehension = 1/(2**precision) The interpretation: "Say nothing and everybody will understand." Where is the declaration of main? How can a source that consists *entirely* of preprocessor directives define any function at all? Run it through your cpp with all #defines expanded and you will be left with -- nothing! To be precise, only the three #include directives survive. (Doesn't this strongly suggest an award for the "Worst abuse of the preprocessor"?) The key is the inclusion of . On any system I know of, errno.h has at least one declaration of errno that looks like extern int errno; I delete the "extern" by replacing it with a comment. Then I replace "errno" with "main(){ ... }" But now there is a semicolon lurking that would cause a syntax error. Thus I tack on another declaration "int errno". So the above line looks somewhat like int main(){ ... } int errno; which, of course, compiles cleanly everywhere I tried it. It even lints without complaint (Solaris Sunpro Lint). Run it through indent, what will happen? Nothing again! Sun's C Beautifier cb(1) also leaves the Apollo 13 rocket right next to its launch tower. The head of the launch tower (_POSIX_SOURCE) makes sure inclusion of errno.h does not give all those vendor extensions that may prevent a clean compilation and lint session because of the redefined extern keyword. The -I/usr/include in the build file is needed by gcc on Solaris because gcc's "fixed" header in gcc-lib/sparc-sun-solaris2.5/2.7.2/include/errno.h is broken (sort of) because it has *two* identical extern declarations of errno. This leads to an error due to the redefinition of main. The -I option makes sure the working /usr/include/errno.h is found first, which shouldn't harm on other systems. Usage ----- The program is run without arguments. It prints all dates in order.