#if __TCPLUSPLUS__ || __STDC__ # define __NSTDC__ 1 #endif /* ---------------------------------------------------------------------- */ /* Copyright (C) 1991 by Natuerlich! */ /* This file is copyrighted! */ /* Refer to the documentation for details. */ /* ---------------------------------------------------------------------- */ /* compile and run this file TWICE */ /* Littleendian means $12345678 -> 12 34 56 78 */ /* Bigendian means $12345678 -> 78 56 34 12 */ /* this is stylistically pretty outdated, yet helpful */ #define HAVEFUN 0 /* to test your compiler a bit more set to 1 */ /* » <-- Error ?? (see EOF) */ #define PHILOSOPHICAL_PROBLEM 1 #define IOCHECK 1 #define SIGNAL 1 /* MS-C does not define SIGSEGV properly */ #define STRICT 0 #define STDIO #if ! __NSTDC__ # define signed #endif #ifdef TOS # define OS 1 #else # ifdef MSDOS # define OS 2 # else # ifdef UNIX # define OS 3 # else # define OS -1 /* unknown OS */ # endif # endif #endif #ifdef TOS # undef TOS #endif #define TOS 1 #ifdef MSDOS # undef MSDOS #endif #define MSDOS 2 #ifdef UNIX # undef UNIX #endif #define UNIX 3 #ifdef UNKNOWN # undef UNKNOWN #endif #define UNKNOWN -1 #if OS == TOS # define Fkreate( p, m) Fcreate( p, 0) # define Perror( s) # if __TURBOC__ # include # else # include # endif # define OPEN_W 0 # define OPEN_R 1 # define OPEN_RW 2 # define fbyte_t long #else # include "xosbind.h" # if OS == MSDOS # define Perror( s) # ifdef OPEN_W # undef OPEN_W # undef OPEN_R # undef OPEN_RW # endif # define OPEN_W O_WRONLY # define OPEN_R O_RDONLY # define OPEN_RW O_RDWR # define fbyte_t long # endif # if OS == UNIX # include # define Perror( s) perror( s) # ifdef OPEN_W # undef OPEN_W # undef OPEN_R # undef OPEN_RW # endif # define OPEN_W O_WRONLY # define OPEN_R O_RDONLY # define OPEN_RW O_RDWR # define fbyte_t unsigned # endif # if OS == UNKNOWN # define Perror( s) # define OPEN_W 1 # define OPEN_R 0 # define OPEN_RW 2 # define fbyte_t unsigned int # endif #endif #include #include STDIO /* Error ? not too bad, reedit OSBINDs in NASM */ #include #if __TURBOC__ # pragma warn -rvl /* instead of very pretty */ # pragma warn -pia /* Don't want those if( foo = bar) warnings */ # pragma warn -pro /* Also we don't care about prototypes anymore */ # pragma warn +sig /* (used to, but that's all over now) */ # pragma warn +use # pragma warn +stv # pragma warn +amb # pragma warn +amp #endif #if OS == TOS typedef long off_t; #endif #if SIGNAL # include # if OS == UNIX || OS == UNKNOWN || defined( __GNUC__) # define SIGADR SIGBUS # else # if OS == MSDOS # define SIGADR SIGSEGV # endif # endif #endif #if __TURBOC__ && OS == TOS # include #endif #if OS == MSDOS # include # include #endif #if OS == UNIX # include #else # if OS == TOS || OS == MSDOS # define SEEK_SET 0 # define SEEK_CUR 1 # define SEEK_END 2 # endif #endif #include "localdef.h" /* ---------- FROM HERE ON EVERYTHING SHOULD WORK ---------- */ #define byte unsigned _BYTE #define word unsigned _WORD #define lword unsigned _LONG #define sbyte signed _BYTE #define sword signed _WORD #define slword signed _LONG #define WRITE( s) fprintf( stderr, s) /* HP cc can't take this (bastard compiler) so comment it out */ /* Sun cc doesn't cope either */ /* #if __NSTDC__ # undef FOO # define FOO 1 # ifndef FOO # error "Compiler can not handle #define/#undef properly" # endif # if ! FOO # error "That should not have happened" # endif # ifdef BAR # error "Throw your compiler away" # endif # undef FOO # ifdef FOO # error "Compiler can not handle #define/#undef properly" # endif #endif */ /* till here */ #undef FOO #if __NSTDC__ # define FOO( a, b, c) a ## b ## c # define BAR( a, b, c) a##b##c # define BAZ( a, b, c) a/**/b/**/c #else # define FOO( a, b, c) a/**/b/**/c #endif FILE *fp, *fopen(); int (*sdf)(); #if ! HAVEFUN || __NSTDC__ int even; #else even; /* Just for fun. This is same as int even; and */ /* shouldn't give an error */ #endif #if __NSTDC__ # if SIGNAL void dofoo( int); # endif extern void exit( int); void xcontinue( int); #else void xcontinue(); #endif #if SIGNAL void dofoo( foo) { if( foo == SIGADR) /* One less warning */ WRITE( "WORDs must lie on an even address\n"); else WRITE( "FUN! Signal out of nowhere\n"); even++; xcontinue(0); } #endif #if ! HAVEFUN struct bar { lword a; word b; byte c; } fx = { 0x55AACC33L, 0x5AC3, 0x5A }; #endif word x = 0x8000, y; word i; byte c = 0x80, *p, *q; lword bar; sbyte *foo; void xcontinue( fd) { #if SIGNAL if( ! fd) { if( ! even) { WRITE( "WORD access on odd address is OK!\n"); fprintf( fp, "#ifndef WORD_EVEN\n#define WORD_EVEN 0\n#endif\n\n"); } else fprintf( fp, "#ifndef WORD_EVEN\n#define WORD_EVEN 1\n#endif\n\n"); fclose( fp); if( signal( SIGADR, (void (*)()) sdf) == SIG_ERR) WRITE( "More fun w/SIGNAL\n"); } #endif #if IOCHECK # if OS == MSDOS _fmode = O_BINARY; # endif { #if HAVEFUN struct bar /* Loser compilers will throw up on this. */ { /* try a static if you like here as well */ lword a; word b; byte c; } fx = { 0x55AACC33L, 0x5AC3, 0x5A }; #endif byte y; lword z; if( (fd = (int) Fkreate("foo.foo", 0644)) < 0) { WRITE( "Why did the creat fail ?\n"); Perror( "hint:"); goto fuckthis; } close( fd); fuckthis: if( (fd = (int) Fopen("foo.foo", OPEN_W)) < 0) { WRITE( "Couldn't open foo.foo for writing.. WHY??\n"); Perror( "hint:"); goto fuckoff; } if( Fwrite( fd, (fbyte_t) sizeof( struct bar), &fx) != (fbyte_t) sizeof( struct bar)) { WRITE( "Didn't write correct number of bytes. Mighty peculiar\n"); goto fuckoff; } close( fd); if( (fd = (int) Fopen("foo.foo", OPEN_R)) < 0) { WRITE( "Couldn't open foo.foo for reading. Bastard machinery!!\n"); Perror( "hint:"); goto fuckoff; } lseek( fd, (long) 6, SEEK_SET); if( Fread( fd, sizeof( byte), &y) != sizeof( byte)) WRITE( "lseek went the wrong way\n"); if( y != fx.c) WRITE( "Probably lseek incompatibility or structs are\ higgledy-piggledy [FUN!]\n"); lseek( fd, (long) -7, SEEK_CUR); if( Fread( fd, sizeof( lword), &z) != sizeof( lword)) WRITE( "lseek incompatibility, can't index negatively\n"); if( z != fx.a) WRITE( "Too strange to explain\n"); close( fd); } #endif fuckoff: bar = (lword) foo; if( ! bar) WRITE( "Strange conversion problems\n"); #if SIGNAL WRITE( "If portable crashes in 10 seconds it doesn't matter\n"); # if __TURBOC__ && ! __PUREC__ WRITE("It mosty probably will, thanx to TURBO.C"); # endif { sword i = 10; while( i--) { sleep( 1); fputc( '.', stderr); fflush( stderr); } fputc( '\n', stderr); } #endif exit( 0); } main( argc, argv) sbyte **argv; { fp = stdout; /* done her 'coz of some Amiga cc's lameness */ i = x; p = (byte *) &i, q = (byte *) &x; foo = (sbyte *) p; if( argc != 1) if( ! (fp = fopen("localdef.h", "w"))) { WRITE( "Sorry couldn't open \"localdef.h\"\n"); exit(1); } sdf = (int (*)()) main; if( (sword) i > 0 || (sbyte) c > 0) { WRITE( "ERROR: Machine/compiler doesn't use 2's complement\ . Don't worry about this\n the first time."); } for( i = 0; i < 256; i++) if( (c = i) != i) WRITE( "ERROR: Most probably chars are just 7 bits\n"); c = i; if( c) WRITE( "ERROR: chars are longer than 8 bit (or abnormal)\n"); y = 2; i = 1; x = FOO( y-,--i,-1); if( x) #if ! __NSTDC__ fprintf( fp, "#ifndef CANCONCAT\n#define CANCONCAT 2\n#endif\n\n"); else WRITE( "Comments can't be used to concatenate (impossible to port)\n"); #else { WRITE( "Compiler can't concatenate token ## token\n"); y = 2; i = 1; x = BAR( y-,--i,-1); if( x) { WRITE( "and can't concatenate text##text as well\n"); y = 2; i = 1; x = BAZ( y-,--i,-1); if( x) WRITE( "Even text/**/text doesn't work (impossible to port)\n"); else { WRITE( "but text/**/text does it \n"); fprintf( fp, "#ifndef CANCONCAT\n#define CANCONCAT 0\n#endif\n\n"); } } WRITE( "but text##text works \n"); fprintf( fp, "#ifndef CANCONCAT\n#define CANCONCAT 1\n#endif\n\n"); } else { WRITE( "Compiler likes to concatenate with text ## text\n"); x = 3; x = BAR( x-,--1,-1); if( x) { WRITE( "But it can't concatenate text##text (which NASM uses)\n"); i = 1; x = 3; x = BAZ( x-,--i,-1); if( x) { WRITE( "And text/**/text doesn't work either. You should set\n\ -DSUN in the CFLAGS definition of \"makefile.nix\"\n"); putc( 7, stderr); fflush( stderr); sleep( 5); } else { WRITE( "But text/**/text does it \n"); fprintf( fp, "#ifndef CANCONCAT\n#define CANCONCAT 0\n#endif\n\n"); } } else { WRITE( "And text##text does work! GREAT!\n"); fprintf( fp, "#ifndef CANCONCAT\n#define CANCONCAT 1\n#endif\n\n"); } } #endif /* If this kills your compiler, that's because it thinks that */ /* casting a pointer doesn't make it an lvalue any more. */ /* [which from my point of view is WRONG, but maybe according */ /* to ANSI. &%$* ANSI as I might add.] */ #if ! PHILOSOPHICAL_PROBLEM { char d[4]; long *c = (long *) d; *((char *) c)++ = 0; if( ((char *) c - 1) != (void *) d) WRITE( "Philosophical problem, Casting before ++ doesn't work\n"); c = (long *) d; *(char *)c++ = 0; if( ((char *) c - sizeof( long)) != (char *) d) WRITE( "Casting before ++ works, where it shouldn't have\n"); } #endif { #define BYTES (sizeof( long) << 2) char x[ BYTES]; long *p = (long *) x; int i; for( i = 0; i < BYTES; x[i++] = 0xFF); *p = *p++ = *p++ = *p++ = 0; for( i = 0; i < BYTES; i++) if( x[i]) { WRITE( "Compiler has it's own ideas where it should ++\n"); fprintf( fp, "#ifndef LATEPLUSPLUS\n#define LATEPLUSPLUS 1\n#endif\n\n"); WRITE( "Set LATEPLUSPLUS to 1\n"); goto fooble; } fprintf( fp, "#ifndef LATEPLUSPLUS\n#define LATEPLUSPLUS 0\n#endif\n\n"); fooble: if( i == BYTES) { i = 1; if( p++, i--) WRITE( "Compiler does --,++ as expected\n"); else WRITE( "Compiler does --,++ not quite as\ expected (but it doesn't matter for NASM)\n"); } } { unsigned long x = ~0; unsigned int y = ~0; unsigned short z = ~0; unsigned int i, j, k, l; if( sizeof( size_t) == 2) { fprintf( stderr, "AHH!! PC detected. **BARF,RETCH**\n"); fprintf( fp, "#define FUCKING_STOOPID_KLUDGE_SHIT 1\n\n"); } for( i = 0; x; x >>= 1, i++); fprintf( stderr, "Unsigned longs have apparently %d bits\n", i); for( j = 0; y; y >>= 1, j++); fprintf( stderr, "Unsigned ints have apparently %d bits\n", j); for( k = 0; z; z >>= 1, k++); fprintf( stderr, "Unsigned shorts have apparently %d bits\n", k); y = (byte) -1; for( l = 0; y; y >>= 1, l++); fprintf( stderr, "Unsigned chars have apparently %d bits\n", l); if( k == 16) fprintf( fp, "#define _WORD short\n"); else if( j == 16) fprintf( fp, "#define _WORD int\n"); else WRITE( "ERROR: No 16bit data type in sight (use bitfields??)\n"); if( j == 32) fprintf( fp, "#define _LONG int\n"); else if( i == 32) fprintf( fp, "#define _LONG long\n"); else WRITE( "ERROR: No 32bit data type in sight (use bitfields??)\n"); if( l == 8) fprintf( fp, "#define _BYTE char\n"); else if( k == 8) fprintf( fp, "#define _BYTE long\n"); else WRITE( "ERROR: No 8bit data type in sight (use bitfields??)\n"); } WRITE( "If you got ERRORs above, or if the data types aren't set correctly\ yet\nthen diagnostics may be incorrect\n\n"); #ifdef __NSTDC__ # if __NSTDC__ WRITE( "ANSI Compiler. ALL RIGHT!!\n"); # else WRITE( "ANSI Compiler ? Then why isn't __STDC__ 1 ?\n"); # endif #endif i = 0x1234; p = (byte *) &i; if( *p == 0x12 && p[1] == 0x34) { WRITE( "Computer is LITTLE-ENDIAN (Lilliput)\n"); fprintf( fp, "\n#ifndef LITTLEENDIAN\n#define LITTLEENDIAN 1\n#endif\n\n"); } else if( *p == 0x34 && p[1] == 0x12) { WRITE( "Computer is BIG-ENDIAN (Blefuscu)\n"); fprintf( fp, "\n#ifndef BIGENDIAN\n#define BIGENDIAN 1\n#endif\n\n"); } else { WRITE( "Computer is weird (Brobdignang (sp?))\n"); fprintf( stderr, "I expected $12 $34 or $34 $12 but got\ $%02X $%02X\n", (word) *p, (word) p[1]); } i = -10000; x = i; if( *p != *q || p[1] != q[1]) { WRITE( "Conversion takes place between int and unsigned\n"); x = (word) i; if( *p != *q || p[1] != q[1]) WRITE( "Which can be suppressed with casting\n"); } #if SIGNAL if( (sdf = (int (*)()) signal( SIGADR, dofoo)) == (int (*)()) SIG_ERR) { WRITE( "Signal could not be set\n"); goto over; } else { slword i; sword *p = (sword *) ((char *) &i + 1); register sword x = (sword) 0x1234; *p = x; /* TOS TURBO-C crashes here, cause they do signalling wrong */ } /* therefore we call continue from dofoo */ #endif xcontinue( 0); #if SIGNAL over: xcontinue( 1); #endif } /* » Did the little cross (ASCII==187) produce an error ? Can your compiler only grok 7bit ASCII ? NO PROBLEM. You can filter out any ASCII character over 127 w/o compromising source integrity. --- never tested nor compiled --- #include main( argc, argv) char *argv[]; { register FILE *fp, *fq; register int c; fp = fopen( argv[1], "r"); fq = fopen( argv[2], "w"); while( (c = (int) getc( fp)) != EOF) if( (char) c >= 0) putc( c, fq); } ACKs & REFs Danny Cohen ON HOLY WARS AND A PLEA FOR PEACE (IEN 137 ??) Patrick Hayes COMPUTER ARCHITECTURE AND ORGANIZATION */