#include #include #include static void GenerateShuffledArray(int count, int *output) { int i, tmp; for(i = 0; i < count; i++) output[i] = i; for(; --count > 1;) { i = rand() % (count + 1); tmp = output[i]; output[i] = output[count]; output[count] = tmp; } } static int ExtractBits(int seed, int *bit_indices) { int i, o; for(i = o = 0; i < 8; i++) { if( (seed & (1 << bit_indices[i])) != 0 ) o |= 1 << i; } return o; } int main(int argc, char **argv) { int seed, i, max_step_bits, b2, b3, b5, size, bit_indices[16]; if( argc != 2 || sscanf(argv[1], "%d", &seed) != 1 || seed < 1 || seed > 65535 ) { return printf("%s [16-bit PIN] < input.txt > output.c\n", *argv); } srand(time(NULL)); GenerateShuffledArray(16, bit_indices); /* Decoder header. */ puts("#ifndef PIN\n" "#error Please compile with -DPIN=\n" "#else\n" "#ifndef _\n" "#define _ __FILE__"); /* Initialize PIN bits. */ for(i = 0; i < 16; i++) { printf("#if PIN %% %d > %d\n" "#define BIT%d\n" "#endif\n", 2 << i, (1 << i) - 1, i); } /* Initialize maximum number of steps to be at least 8 bits. This is needed since we use the step counter for both running PRNG and also for building characters, so we need at least 8 bits to support all possible character outputs even if the maximum number of steps between PRNG runs can be represented in less than 8 bits. */ max_step_bits = 8; /* Data array. */ puts("static const unsigned char data[] = {"); size = 0; while( (i = getchar()) != EOF ) { /* Count number of steps needed to advance PRNG, with a minimum bound so that consecutive equal bytes will still advance the PRNG some number of times. */ b2 = (rand() % 16) + 1; for(b3 = 0; b3 < b2 || ExtractBits(seed, bit_indices) != i; b3++) { b5 = seed ^ (seed >> 2) ^ (seed >> 3) ^ (seed >> 5); seed = ((seed >> 1) | (b5 << 15)) & 0xffff; } /* Output directives to advance PRNG steps. */ puts("#define OUTPUT_BYTE"); for(b2 = 0; b3 >= (1 << b2); b2++) { if( (b3 & (1 << b2)) != 0 ) printf("#define STEP%d\n", b2); } if( max_step_bits < b2 ) max_step_bits = b2; puts("#include _"); size++; } /* Decoder footer. */ printf("};\n" "#include\n" "int main() { return !fwrite(data, %d, 1, stdout); }\n" "#else\n" "#ifdef OUTPUT_BYTE\n" "#undef OUTPUT_BYTE\n" "#define RUN_PRNG\n" "#include _\n", size); /* Convert PRNG bits to byte increment bits. */ for(i = 0; i < 8; i++) { printf("#ifdef BIT%d\n" "#define STEP%d\n" "#endif\n", bit_indices[i], i); } /* Generate byte and start next byte. */ puts("#undef RUN_PRNG\n" "#include _\n" "0,\n" "#else"); /* Run PRNG steps. */ for(i = max_step_bits - 1; i > 0; i--) { printf("#ifdef STEP%d\n" "#undef STEP%d\n" "#include _\n" "#define STEP%d\n" "#include _\n" "#define STEP%d\n" "#endif\n", i, i, i - 1, i - 1); } /* Run a single step of PRNG, or increment pending byte by 1. */ puts("#ifdef STEP0\n" "#undef STEP0\n" "#ifdef RUN_PRNG\n" "#undef BIT16"); /* Using linear feedback shift register, bit16 = bit0^bit2^bit3^bit5 */ for(b2 = 2; b2--;) { puts(b2 ? "#ifdef BIT2" : "#else"); for(b3 = 2; b3--;) { puts(b3 ? "#ifdef BIT3" : "#else"); for(b5 = 2; b5--;) { puts(b5 ? "#ifdef BIT5" : "#else"); puts((b2 ^ b3 ^ b5) == 1 ? "#ifndef BIT0" : "#ifdef BIT0"); puts("#define BIT16\n" "#endif"); if( !b5 ) puts("#endif"); } if( !b3 ) puts("#endif"); } if( !b2 ) puts("#endif"); } /* seed = (bit16 | seed) >> 1 */ for(i = 0; i < 16; i++) { printf("#undef BIT%d\n" "#ifdef BIT%d\n" "#define BIT%d\n" "#endif\n", i, i + 1, i); } puts("#else\n" "-~\n" "#endif\n" /* #ifdef RUN_PRNG */ "#endif\n" /* #ifdef STEP0 */ "#endif\n" /* #ifdef OUTPUT_BYTE */ "#endif\n" /* #ifdef _ */ "#endif"); /* #ifdef PIN */ return 0; }