/* codegen.c (lain.c) - Random code generator Don Yang (uguu.org) Reads template from stdin, writes code to stdout. Doesn't work too well if first word in input is not long enough. Also, it's not guaranteed to fit the input template, but it will fit pretty close most of the time. If you feed it a binary file or something with tabs, though, the result is undefined (bad). The output code is guaranteed to... 1. Compile with gcc, but with lots of warnings 2. Produce different output for different command line input (usually) 3. Output using only characterse given in its arguments 4. Halt in finite time 5. Not give runtime errors 6. Not pass lint So it takes some input and gives some output, therefore it's a valid (although probably useless) program. But who knows, generate one billion programs and maybe one of them will generate an encyclopedia ;) Okay, so the the output program is pretty lame. But if it was that easy, I would be out of business ^_^;; 08/11/00 */ #include #include #include #define MAX_TEMPLATE_SIZE 512 #define MAX_OUTPUT_SIZE 9999 #define INIT_OUTPUT_SIZE 183 #define INIT_LEAF_COUNT 4 #define EXPR_COUNT 8 #define TERMINAL_COUNT 16 /* General variables (all variables are global) */ static int i, j, k, e, s; /* Output status */ static int length = INIT_OUTPUT_SIZE; static int leaf = INIT_LEAF_COUNT; static int length0, leaf0; /* Output string X = 2 character token follows (ASCII 88) Y = 3 character token follows (ASCII 89) Z = 4 character token follows (ASCII 90) @ = generate expression here */ static char code[MAX_OUTPUT_SIZE] = "Zenum" "{" "x=Y127,y,z" "};" "Zchar t[z];" "Yint i,j,k;" "Zmain(Yint c,Zchar**a)" "{" "Yfor(i=j=t[x]=t[y]=0;i ' ' ) { charcount++; if( template[tindex] > 0 ) ++template[tindex]; else template[++tindex] = 1; } else { if( template[tindex] < 0 ) template[tindex]--; else template[++tindex] = -1; } } template[++tindex] = MAX_OUTPUT_SIZE; } /* GetTemplate() */ /* Shift string */ static void Shift(int start, int offset) { for(s = 0; code[s]; s++); for(; s >= start; code[s-- + offset] = code[s]); } /* Shift() */ /* Insert expressions */ static void InsertTree(void) { /* Loop until output code size is equal to template size */ for(; length < charcount;) { /* Find random leaf position */ k = rand() % leaf; for(i = j = 0; j <= k; i++) { if( code[i] == '@' ) j++; } i--; /* i = index of insert position */ /* Select random expression */ length0 = length--; leaf0 = leaf--; do { e = rand() % EXPR_COUNT; length0 = length; leaf0 = leaf; for(j = 0; expr[e][j]; j++) { if( expr[e][j] == '@' ) leaf0++; length0++; } } while( length0 > charcount + 1 ); length = length0; leaf = leaf0; /* Insert expression */ Shift(i, j - 1); for(k = 0; expr[e][k]; code[i + k++] = expr[e][k]); } } /* InsertTree() */ /* Complete expression tree */ static void InsertLeaf(void) { for(i = 0; code[i]; i++) { if( code[i] == '@' ) code[i] = terminal[rand() % TERMINAL_COUNT]; } } /* InsertLeaf() */ /* Write output */ static void WriteOutput(void) { /* Reset indexes. Continues output until all code characters are written, not when the template is out of characters. tindex = template index k = number of characters exceeding last template token i = output code index */ for(tindex = i = k = 0; code[i]; tindex++) { if( template[tindex] ) { /* Need to write code or space */ if( template[tindex] > 0 ) { /* Set output token length */ if( code[i] >= 'X' && code[i] <= 'Z' ) j = code[i++] - 'V'; else j = 1; /* Write token */ for(; j-- > 0; template[tindex]--) { if( k ) k--; else putchar(code[i++]); } /* Adjust template */ if( template[tindex] > 0 ) tindex--; else k = -template[tindex]; } else { /* Write spaces */ for(; template[tindex]; template[tindex]++) { if( k ) k--; else putchar(' '); } } } else { /* template[i] == 0 -> write newline */ putchar('\n'); k = 0; } } putchar('\n'); } /* WriteOutput() */ /* main */ int main(void) { srand((unsigned)time(NULL)); GetTemplate(); InsertTree(); InsertLeaf(); WriteOutput(); return 0; } /* main() */