/* No conditional branches! What that applies: 1. any loops forbidden, 2. printf() forbidden for it has to lookup placeholders in the pattern, 3. NUL-terminated strings are useless, due to testing for '\0' is forbidden; 4. (!!!) do not use libc, due to many conditional statements in every function Usage: gcc -Wall -Wextra -Wl,-s -nostdlib 99-bottles-of-beer.c ... or ... gcc -nostdlib 99-bottles-of-beer.c Dependencies: x86 arch with Linux Idea: http://www.99-bottles-of-beer.net/ */ const char wall[12] = " on the wall"; const char take[65] = "Go to the store and buy some moreTake one down and pass it around"; /* quit() - syscall exit() */ static void quit(int a) { (void) a; asm volatile ("int $0x80" : : "a" (1), "b" (0)); } /* write() - syscall write() with fd = 1 */ static void write(const char *buf, long size) { asm volatile ("int $0x80" : : "a" (4), "b" (1), "c" (buf), "d" (size)); } /* p() - return 1 for any positive integer and 0 otherwise */ static unsigned char p(char n) { return ( (unsigned char) -n ) >> 7 ; } /* putTail() - print "" for 1 and "s" otherwise */ static void putTail(char n) { write("s", p((n - 1) & 0x7F)) ; } /* putNum() - print out number of bottles n - number of bottles cap - if the first letter should be capitalized */ static void putNum(char n, char cap) { int length = 1 + p(n / 10) + 6 * (1 - p(n)); static char a[9] = "..no more"; a[0] = '0' + (n / 10); a[1] = '0' + (n % 10); a[2] = 'N' * p(cap) + 'n' * (1 - p(cap)); write(a + 1 - p(n / 10) + 1 * (1 - p(n)), length); } /* putPhrase() - print out phrase counting bottles n - number of bottles cap - if the 1st letter should be capital */ static void putPhrase(char n, char cap) { putNum(n, cap); write(" bottle", 7); putTail(n); write(" of beer", 8); } /* putLine() - print out the 2nd line of the verse */ static void putLine(char n) { write(take + 33 * p(n), 33 - p(n)); write(", ", 2); putPhrase(n - 1 + 100 * (1 - p(n)), 0); write(wall, 12); write(".\n\n", 3); } /* putVerse() - print out the verse */ static void putVerse(int num) { putPhrase(num, 1); write(wall, 12); write(", ", 2); putPhrase(num, 0); write(".\n", 2); putLine(num); } int _start() { void *funcs[] = { &quit, &putVerse }; void (*foo) (int); char cx = 99; again: foo = funcs[p(cx + 1)]; foo(cx--); goto again; quit(0); return 0; /* convenience */ }