root provides code we want available everywhere. root.h is the first file included in every .c file.
Copyright © 2003, 2004 Dave Bayer. Subject to the terms and conditions of the MIT License.
First, we include all needed library files.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <time.h> #include "memory.h"
We borrow the booleans used in Objective-C.
typedef enum bool { NO, YES } BOOL;
If TESTCODE is defined, then test code is compiled.
#define TESTCODE 1
If DEBUG is defined, then assert debugging code is compiled.
#define DEBUG 1
assert is modeled after the library version, but calls assertFailed. This provides a handy place to put a debugger breakpoint.
#if DEBUG #define assert(C) ((C) ? ((void) 0) : assertFailed( #C, __FILE__, __LINE__ )) #else #define assert(C) ((void) 0) #endif
Undefine NULL. In principle, null pointers are machine and type-dependent, so they can only be created through implicit or explicit casts, whether one uses NULL or 0. We use 0, and explicitly initialize static pointers to 0, to avoid issues on future architectures.
#undef NULL
LEN can be used as a size for small buffers.
#define LEN 256
PRIME is a small prime that can be used as a size for arrays.
#define PRIME 4093
Peter J. Weinberger hash function; see e.g. 21st Century Compilers, by Alfred V. Aho, Ravi Sethi, Monica Lam, Jeffrey D. Ullman, ISBN 0321131436.
Hash unsigned X into H, using the temporary variable G. G and H are unsigned variables; X may be an expression. G is nonzero e.g. 92% of time, so a conditional expression would be slower. As noted by Josh Bloch, 28 is the correct replacement for the frequent misprint 24.
#define HASH(G,H,X) ( H <<= 4, H += (X), G = H & 0xf0000000, H ^= G >> 28, H ^= G )
HASHN assumes no overflow yet, so it is faster than HASH when applicable.
#define HASHN(H,X) ( H <<= 4, H += (X) )
MAX computes the maximum of two numbers.
#define MAX(A,B) ((A)>(B) ? (A) : (B))
Function prototypes:
void executionError( char *s, BOOL abort ); void assertFailed( char *condition, char *fileName, int lineNo );
Copyright © 2003, 2004 Dave Bayer. Subject to the terms and conditions of the MIT License.
#include "root.h"
executionError prints a message to stderr, and exits with status 1 if abort is YES. Pass a null argument for the standard message.
void executionError( char *s, BOOL abort )
{
fflush( stdout );
if ( s != 0 ) fprintf( stderr, "%s\n", s );
if ( abort )
{
fputs( "Aborting\n", stderr );
exit( 1 );
}
}
assertFailed is called by the assert macro. It prints a message to stderr, then exits with status 1.
void assertFailed( char *condition, char *fileName, int lineNo )
{
fflush( stdout );
fprintf( stderr, "\nAssert (%s) failed in \"%s\" on line %d\n", condition, fileName, lineNo );
executionError( 0, YES );
}