1 /*
2 The Evil Finder
3 Copyright (C) 2002 by Michal Zalewski <lcamtuf@coredump.cx>
4 */
5
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <fcntl.h>
11 #include <ctype.h>
12 #include <sys/time.h>
13 #include <signal.h>
14
15 #define MAXOPT 1024
16 #define MAXBUF 1024
17 #define MINNEST 3
18 #define MAXNEST 5
19
20 #define MAXRES 1
21
22 struct Trec {
23 int num;
24 char* desc;
25 };
26
27
28
29 struct proof {
30 int nest;
31 char* prolog;
32 int usednum[MAXNEST+2];
33 int utop;
34 char how[MAXBUF];
35 int val;
36 };
37
38
39 struct Trec options[MAXOPT];
40 struct Trec final[MAXOPT];
41
42 char* rprolog[MAXRES];
43 char* results[MAXRES];
44 int restop;
45
46
47 int opttop, fintop;
48
49 #define fatal(x) exit(printf("<p><font color=red><b>FATAL: <i>%s</i></b></font>",x)?1:1)
50
51
backwardize(int z)52 int backwardize(int z) {
53 // Laaame.
54 char buf[128],b2[128];
55 int i,q;
56 if (z<0) return -31337000;
57 sprintf(buf,"%d",z);
58 q=strlen(buf);
59 for (i=0;i<q;i++) b2[q-i-1]=buf[i];
60 b2[q]=0;
61 if (!strcmp(b2,buf)) return -31337000;
62 return atoi(b2);
63 }
64
backstring(int z)65 char* backstring(int z) {
66 // Laaame.
67 char buf[128];
68 static char b2[128];
69 int i,q;
70 if (z<0) return "<error>";
71 sprintf(buf,"%d",z);
72 q=strlen(buf);
73 for (i=0;i<q;i++) b2[q-i-1]=buf[i];
74 b2[q]=0;
75 if (!strcmp(b2,buf)) return "<error>";
76 return b2;
77 }
78
79
tooctal(int z)80 int tooctal(int z) {
81 // Laaame.
82 char buf[128];
83 if (z<0) return -31337000;
84 sprintf(buf,"%o",z);
85 if (atoi(buf) == z) return -31337000;
86 return atoi(buf);
87 }
88
89
90 int rf=-1;
91
get_random(void)92 unsigned int get_random(void) {
93 int val;
94 if (rf<0) {
95 rf=open("/dev/urandom",O_RDONLY);
96 if (rf<0) { perror("/dev/urandom"); exit(1); }
97 }
98 read(rf,&val,4);
99 return val;
100 }
101
102
trace_proof(struct proof * p)103 void trace_proof(struct proof* p) {
104 int i,a;
105 char order[12]={0,1,2,3,4,5,6,7,8,9,10,11};
106
107
108 // Whoops. Bail out.
109 if (restop >= MAXRES) return;
110
111 // Check for "proven' conditions.
112 if (p->nest>=MINNEST && p->val>0)
113
114 for (i=0;i<fintop;i++) {
115
116 // Straight
117 if (p->val == final[i].num) {
118 char buf[MAXBUF*2];
119 strcpy(buf,p->how);
120 sprintf(&buf[strlen(buf)],"The number %d is %s.\n<p>\n<b>This clearly proves how evil the subject is. QED.\n",final[i].num,final[i].desc);
121 rprolog[restop]=p->prolog;
122 results[restop++]=strdup(buf);
123 // printf("PROOF %d: %s\n",restop,buf);
124 return;
125 }
126
127 // In reverse
128 if (p->val == backwardize(final[i].num)) {
129 char buf[MAXBUF*2];
130 strcpy(buf,p->how);
131 sprintf(&buf[strlen(buf)],"This number, read from right to left, is %d, or %s.\n<p>\n<b>No further questions. QED.\n",final[i].num,final[i].desc);
132 rprolog[restop]=p->prolog;
133 results[restop++]=strdup(buf);
134 // printf("PROOF %d: %s\n",restop,buf);
135 return;
136 }
137
138 // The result in octal is...
139 if (tooctal(p->val) == final[i].num) {
140 char buf[MAXBUF*2];
141 strcpy(buf,p->how);
142 sprintf(&buf[strlen(buf)],"This, written in octal, is %d, %s.\n<p>\n<b>It speaks for itself. QED.\n",final[i].num,final[i].desc);
143 rprolog[restop]=p->prolog;
144 results[restop++]=strdup(buf);
145 // printf("PROOF %d: %s\n",restop,buf);
146 return;
147 }
148
149 // The result is ..., which in octal...
150 if (p->val == tooctal(final[i].num)) {
151 char buf[MAXBUF*2];
152 strcpy(buf,p->how);
153 sprintf(&buf[strlen(buf)],"This number, read as octal, gives %d - %s.\n<p>\n<b>This is truly evil. QED.\n",final[i].num,final[i].desc);
154 rprolog[restop]=p->prolog;
155 results[restop++]=strdup(buf);
156 // printf("PROOF %d: %s\n",restop,buf);
157 return;
158 }
159
160 // The result in octal is ... backwards
161 if (tooctal(p->val) == backwardize(final[i].num) && tooctal(p->val)>0) {
162 char buf[MAXBUF*2];
163 strcpy(buf,p->how);
164 sprintf(&buf[strlen(buf)],"This, written in octal, is %d. This, read backwards, gives %d, %s.\n<p>\n<b>No doubt about its evilness. QED.\n",tooctal(p->val),final[i].num,final[i].desc);
165 rprolog[restop]=p->prolog;
166 results[restop++]=strdup(buf);
167 // printf("PROOF %d: %s\n",restop,buf);
168 return;
169 }
170
171 // The result is ..., which in octal is ... backwards
172 if (backwardize(p->val) == tooctal(final[i].num) && backwardize(p->val)>0) {
173 char buf[MAXBUF*2];
174 strcpy(buf,p->how);
175 sprintf(&buf[strlen(buf)],"This, when read backwards, gives %s. This is %d in octal, %s...\n<p>\n<b>Evil, QED.\n",backstring(p->val),final[i].num,final[i].desc);
176 rprolog[restop]=p->prolog;
177 results[restop++]=strdup(buf);
178 // printf("PROOF %d: %s\n",restop,buf);
179 return;
180 }
181
182 // The result backwards in octal is ...
183 if (tooctal(backwardize(p->val)) == final[i].num) {
184 char buf[MAXBUF*2];
185 strcpy(buf,p->how);
186 sprintf(&buf[strlen(buf)],"This number, when read backwards, gives %s. This, written in octal, gives %d - %s.\n<p>\n<b>Enough said - QED.\n",backstring(p->val),final[i].num,final[i].desc);
187 rprolog[restop]=p->prolog;
188 results[restop++]=strdup(buf);
189 // printf("PROOF %d: %s\n",restop,buf);
190 return;
191 }
192
193 // The result in octal is ... backwards
194 if (p->val == tooctal(backwardize(final[i].num))) {
195 char buf[MAXBUF*2];
196 strcpy(buf,p->how);
197 sprintf(&buf[strlen(buf)],"Write %d backwards. Translate it to octal - this will give you %d. Thus, %d stands for %d, %s.\n<p>\n<b>You get the picture. QED.\n",final[i].num,p->val,p->val,final[i].num,final[i].desc);
198 rprolog[restop]=p->prolog;
199 results[restop++]=strdup(buf);
200 // printf("PROOF %d: %s\n",restop,buf);
201 return;
202 }
203
204 }
205
206 // Nest level exceeded. Abandon this branch.
207 if (p->nest>=MAXNEST) return;
208
209 // Now, let's try all possibilities:
210
211 // Shuffle check order
212 for (i=0;i<12;i++) {
213 char tmp;
214 int z=get_random() % 12;
215 tmp=order[i];
216 order[i]=order[z];
217 order[z]=tmp;
218 }
219
220 for (a=0;a<12;a++)
221 switch(order[a]) {
222
223 case 0:
224 // Straight addition
225 for (i=0;i<opttop;i++) {
226 struct proof* n;
227 int t;
228 for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip1;
229 n=malloc(sizeof(struct proof));
230 memcpy(n,p,sizeof(struct proof));
231 n->val=p->val+options[i].num;
232 n->usednum[n->utop++]=options[i].num;
233 n->nest++;
234 sprintf(&n->how[strlen(n->how)],"Add %d, %s - the result is %d.\n<p>\n",
235 options[i].num,options[i].desc,n->val);
236 trace_proof(n);
237 free(n);
238 skip1:
239 break;
240 }
241 break;
242
243
244 case 1:
245 // Right reverse addition
246 for (i=0;i<opttop;i++) {
247 struct proof* n;
248 int t;
249 if (backwardize(options[i].num)<0) continue;
250 for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip2;
251 n=malloc(sizeof(struct proof));
252 memcpy(n,p,sizeof(struct proof));
253 n->val=p->val+backwardize(options[i].num);
254 n->usednum[n->utop++]=options[i].num;
255 n->nest++;
256 sprintf(&n->how[strlen(n->how)],"Add %s to it - this is %s, written backwards - you will get %d.\n<p>\n",
257 backstring(options[i].num),options[i].desc,n->val);
258 trace_proof(n);
259 free(n);
260 skip2:
261 break;
262 }
263 break;
264
265
266 case 2:
267 // Left reverse addition
268 for (i=0;i<opttop;i++) {
269 struct proof* n;
270 int t;
271 if (backwardize(p->val)<0) continue;
272 for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip3;
273 n=malloc(sizeof(struct proof));
274 memcpy(n,p,sizeof(struct proof));
275 n->usednum[n->utop++]=options[i].num;
276 n->val=backwardize(p->val)+options[i].num;
277 n->nest++;
278 sprintf(&n->how[strlen(n->how)],"Turn the number backwards, and add %d - %s. The number is now %d.\n<p>\n",
279 options[i].num,options[i].desc,n->val);
280 trace_proof(n);
281 free(n);
282 skip3:
283 break;
284 }
285 break;
286
287 case 3:
288 // Straight subtraction
289 for (i=0;i<opttop;i++) {
290 struct proof* n;
291 int t;
292 if (p->val-options[i].num<100) continue;
293 for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip4;
294 n=malloc(sizeof(struct proof));
295 memcpy(n,p,sizeof(struct proof));
296 n->val=p->val-options[i].num;
297 n->usednum[n->utop++]=options[i].num;
298 n->nest++;
299 sprintf(&n->how[strlen(n->how)],"Subtract %d, %s. The result will be %d.\n<p>\n",
300 options[i].num,options[i].desc,n->val);
301 trace_proof(n);
302 free(n);
303 skip4:
304 break;
305 }
306 break;
307
308 case 4:
309 // Right reverse subtraction
310 for (i=0;i<opttop;i++) {
311 struct proof* n;
312 int t;
313 if (p->val-backwardize(options[i].num)<100) continue;
314 for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip5;
315 n=malloc(sizeof(struct proof));
316 memcpy(n,p,sizeof(struct proof));
317 n->val=p->val-backwardize(options[i].num);
318 n->usednum[n->utop++]=options[i].num;
319 n->nest++;
320 sprintf(&n->how[strlen(n->how)],"Subtract %s from the number - this is %s, written backwards. It gives %d.\n<p>\n",
321 backstring(options[i].num),options[i].desc,n->val);
322 trace_proof(n);
323 free(n);
324 skip5:
325 break;
326 }
327 break;
328
329 case 5:
330 // Left reverse subtraction
331 for (i=0;i<opttop;i++) {
332 struct proof* n;
333 int t;
334 if (backwardize(p->val)-options[i].num<100) continue;
335 for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip6;
336 n=malloc(sizeof(struct proof));
337 memcpy(n,p,sizeof(struct proof));
338 n->val=backwardize(p->val)-options[i].num;
339 n->usednum[n->utop++]=options[i].num;
340 n->nest++;
341 sprintf(&n->how[strlen(n->how)],"Turn the number backwards, subtract %d - %s. The number is now %d.\n<p>\n",
342 options[i].num,options[i].desc,n->val);
343 trace_proof(n);
344 free(n);
345 skip6:
346 break;
347 }
348 break;
349
350 case 6:
351 // Straight multiplication
352 for (i=0;i<opttop;i++) {
353 struct proof* n;
354 int t;
355 if (p->val*options[i].num>30000) continue;
356 for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip7;
357 if ( options[i].num == 1) continue;
358 n=malloc(sizeof(struct proof));
359 memcpy(n,p,sizeof(struct proof));
360 n->val=p->val*options[i].num;
361 n->usednum[n->utop++]=options[i].num;
362 n->nest++;
363 sprintf(&n->how[strlen(n->how)],"Multiply it by %d, %s - the number is now %d.\n<p>\n",
364 options[i].num,options[i].desc,n->val);
365 trace_proof(n);
366 free(n);
367 skip7:
368 break;
369 }
370 break;
371
372 case 7:
373 // Right reverse multiplication
374 for (i=0;i<opttop;i++) {
375 struct proof* n;
376 int t;
377 if (backwardize(options[i].num)<0) continue;
378 if (p->val*backwardize(options[i].num)>30000) continue;
379 if ( options[i].num == 1) continue;
380 for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip8;
381 n=malloc(sizeof(struct proof));
382 memcpy(n,p,sizeof(struct proof));
383 n->val=p->val*backwardize(options[i].num);
384 n->usednum[n->utop++]=options[i].num;
385 n->nest++;
386 sprintf(&n->how[strlen(n->how)],"Multiply the number by %s - this is %s, from right to left. It gives %d.\n<p>\n",
387 backstring(options[i].num),options[i].desc,n->val);
388 trace_proof(n);
389 free(n);
390 skip8:
391 break;
392 }
393 break;
394
395 case 8:
396 // Left reverse multiplication
397 for (i=0;i<opttop;i++) {
398 struct proof* n;
399 int t;
400 if (backwardize(p->val)<0) continue;
401 if (backwardize(p->val)*options[i].num>30000) continue;
402 if ( options[i].num == 1) continue;
403 for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip9;
404 n=malloc(sizeof(struct proof));
405 memcpy(n,p,sizeof(struct proof));
406 n->val=backwardize(p->val)*options[i].num;
407 n->usednum[n->utop++]=options[i].num;
408 n->nest++;
409 sprintf(&n->how[strlen(n->how)],"Turn the number backwards, multiply by %d - %s. The number is now %d.\n<p>\n",
410 options[i].num,options[i].desc,n->val);
411 trace_proof(n);
412 free(n);
413 skip9:
414 break;
415 }
416 break;
417
418 case 9:
419 // Straight division
420 for (i=0;i<opttop;i++) {
421 struct proof* n;
422 int t;
423 if (p->val % options[i].num) continue;
424 if (p->val / options[i].num < 100) continue;
425 if ( options[i].num == 1) continue;
426 for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip10;
427 n=malloc(sizeof(struct proof));
428 memcpy(n,p,sizeof(struct proof));
429 n->val=p->val/options[i].num;
430 n->usednum[n->utop++]=options[i].num;
431 n->nest++;
432 sprintf(&n->how[strlen(n->how)],"Divide by %d, %s - the result is %d.\n<p>\n",
433 options[i].num,options[i].desc,n->val);
434 trace_proof(n);
435 free(n);
436 skip10:
437 break;
438 }
439 break;
440
441 case 10:
442 // Right reverse division
443 for (i=0;i<opttop;i++) {
444 struct proof* n;
445 int t;
446 if (p->val % backwardize(options[i].num)) continue;
447 if (p->val / backwardize(options[i].num) < 100) continue;
448 if ( options[i].num == 1) continue;
449 for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip11;
450 n=malloc(sizeof(struct proof));
451 memcpy(n,p,sizeof(struct proof));
452 n->val=p->val/backwardize(options[i].num);
453 n->usednum[n->utop++]=options[i].num;
454 n->nest++;
455 sprintf(&n->how[strlen(n->how)],"Divide the number by %s - this is %s, backwards. It gives %d.\n<p>\n",
456 backstring(options[i].num),options[i].desc,n->val);
457 trace_proof(n);
458 free(n);
459 skip11:
460 break;
461 }
462 break;
463
464 case 11:
465 // Left reverse division
466 for (i=0;i<opttop;i++) {
467 struct proof* n;
468 int t;
469 if (backwardize(p->val) % options[i].num) continue;
470 if (backwardize(p->val) / options[i].num < 100) continue;
471 if ( options[i].num == 1) continue;
472 for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip12;
473 n=malloc(sizeof(struct proof));
474 memcpy(n,p,sizeof(struct proof));
475 n->val=backwardize(p->val)/options[i].num;
476 n->usednum[n->utop++]=options[i].num;
477 n->nest++;
478 sprintf(&n->how[strlen(n->how)],"Turn the number backwards, divide by %d - %s. The number is now %d.\n<p>\n",
479 options[i].num,options[i].desc,n->val);
480 trace_proof(n);
481 free(n);
482 skip12:
483 break;
484 }
485 break;
486
487 default: fatal("Whoops.\n");
488 }
489
490 // Ok. All set.
491
492 }
493
494
mypow(int what,int cnt)495 int mypow(int what,int cnt) {
496 int i,res=1;
497 for (i=0;i<cnt;i++) res*=what;
498 return res;
499 }
500
501
simplify(int what)502 int simplify(int what) {
503 while (what > 9) what = (what / 10) + (what % 10);
504 return what;
505 }
506
507
508 int stopped;
509 int retrynum;
510
interrupter(int x)511 void interrupter(int x) {
512 restop=MAXRES+1;
513 // printf("...restart.\n");
514 stopped=1;
515 retrynum++;
516 }
517
518
519
520 int asum[10],nsum[10];
521
main(void)522 int main(void) {
523 int z,i,ch=0;
524 FILE* f;
525 unsigned char ibuf[1024],tmp[256];
526
527
528 // We assume we're not in /tmp... how convinient!
529 sprintf(tmp,"/tmp/.tmp-%d-%u",getpid(),(int)time(0));
530 sprintf(ibuf,"/usr/local/libexec/ef-shuffle </usr/local/share/evilfinder/evilnumbers.dat >%s",tmp);
531 system(ibuf);
532
533 f=fopen(tmp,"r");
534 if (!f) fatal("cannot open tmp file\n");
535 unlink(tmp);
536
537 while(fgets(ibuf,sizeof(ibuf),f)) {
538 int num;char* d;
539 if (ibuf[0]=='*') num=atoi(&ibuf[1]); else num=atoi(ibuf);
540 d=ibuf;
541 while (*d && *d!=' ' && *d!='\t') d++;
542 if (!*d) fatal("malformed config file\n");
543 while (*d==' ' || *d=='\t') d++;
544 if (!strlen(d)) fatal("empty description in config file?\n");
545 if (strchr(d,'\n')) *strchr(d,'\n')=0;
546 if (ibuf[0]=='*') {
547 final[fintop].num=num;
548 final[fintop].desc=strdup(d);
549 fintop++;
550 } else {
551 options[opttop].num=num;
552 options[opttop].desc=strdup(d);
553 opttop++;
554 }
555 }
556
557 if (!opttop) fatal("no entries in the config file.\n");
558 if (!fintop) fatal("no exit conditions in the config file.\n");
559
560 fclose(f);
561
562 // printf("Loaded %d config entries, %d of which are exit conditions.\n",opttop,fintop);
563
564 { char* x;
565 x=getenv("QUERY_STRING_UNESCAPED");
566 if (!x) fatal("no input provided.\n");
567 if (strlen(x)>100) fatal("suspiciously long input.\n");
568 if (!strchr(x,'=')) fatal("malformed query string.\n");
569 x=strchr(x,'=')+1;
570 strcpy(ibuf,x);
571 }
572
573 if (strlen(ibuf)<4) fatal("input too short.\n");
574 for (i=0;i<strlen(ibuf);i++) if (isalpha(ibuf[i])) ch++;
575 if (ch<4) fatal("not enough characters (letters).\n");
576 if (strlen(ibuf)>40) fatal("too many characters.\n");
577 if (strchr(ibuf,'<')) fatal("go cross-script yourself.\n");
578
579 z=0;
580
581 for (i=0;i<ch;i++) {
582 int cur=i/(ch/4);
583 while (!isalpha(ibuf[z])) z++;
584 if (cur>4) cur=4;
585 asum[cur]+=simplify(toupper(ibuf[z]));
586 nsum[cur]+=simplify(toupper(ibuf[z])-'A'+1);
587 z++;
588 }
589
590 for (i=0;i<10;i++) { asum[i]=simplify(asum[i]);
591 nsum[i]=simplify(nsum[i]); }
592
593 // printf("asum = %d%d%d%d%d nsum = %d%d%d%d%d (chars = %d)\n",
594 // asum[0],asum[1],asum[2],asum[3],asum[4],
595 // nsum[0],nsum[1],nsum[2],nsum[3],nsum[4],ch);
596
597 retry:
598
599 stopped=0;
600 restop=0;
601 signal(SIGALRM,interrupter);
602 alarm(5+retrynum);
603
604 if (get_random() % 2)
605
606 { struct proof p;
607 int pcur=-1;
608 char t[10000];
609 bzero(t,sizeof(t));
610 bzero(&p,sizeof(p));
611 z=0;
612 for (i=0;i<ch;i++) {
613 while (!isalpha(ibuf[z])) z++;
614 t[strlen(t)]=' ';
615 t[strlen(t)]=' ';
616 t[strlen(t)]=' ';
617 t[strlen(t)]=toupper(ibuf[z]);
618 z++;
619 }
620 strcat(t,"\n");
621 z=0;
622 for (i=0;i<ch;i++) {
623 while (!isalpha(ibuf[z])) z++;
624 sprintf(&t[strlen(t)]," %2d",toupper(ibuf[z])-'A'+1);
625 z++;
626 }
627 strcat(t," - as numbers\n");
628
629 z=0;
630 for (i=0;i<ch;i++) {
631 while (!isalpha(ibuf[z])) z++;
632 sprintf(&t[strlen(t)]," %d",simplify(toupper(ibuf[z])-'A'+1));
633 z++;
634 }
635 strcat(t," - digits added\n ");
636
637 for (i=0;i<ch;i++) {
638 int cur=i/(ch/4);
639 if (cur>4) cur=4;
640 if (pcur!=cur) {
641 if (pcur != -1) strcat(t,"/");
642 strcat(t," \\_");
643 } else strcat(t,"____");
644 pcur=cur;
645 }
646
647 strcat(t,"/\n");
648
649 for (i=0;i<ch;i++) {
650 int cur=i/(ch/4);
651 if (cur>4) cur=4;
652 if (pcur!=cur) sprintf(&t[strlen(t)]," %d",nsum[cur]);
653 else strcat(t," ");
654 pcur=cur;
655 }
656
657 strcat(t," - digits added\n\n");
658
659 if (!nsum[4])
660 p.val=nsum[0]*1000+nsum[1]*100+nsum[2]*10+nsum[3];
661 else
662 p.val=nsum[0]*10000+nsum[1]*1000+nsum[2]*100+nsum[3]*10+nsum[4];
663
664 sprintf(&t[strlen(t)],"Thus, \"%s\" is %d.\n\n",ibuf,p.val);
665
666 p.prolog=strdup(t);
667 p.usednum[0]=p.val;p.utop=1;
668
669 trace_proof(&p);
670
671 }
672
673 else
674
675 { struct proof p;
676 int pcur=-1;
677 char t[10000];
678 bzero(&p,sizeof(p));
679 bzero(t,sizeof(t));
680 z=0;
681 for (i=0;i<ch;i++) {
682 while (!isalpha(ibuf[z])) z++;
683 t[strlen(t)]=' ';
684 t[strlen(t)]=' ';
685 t[strlen(t)]=' ';
686 t[strlen(t)]=toupper(ibuf[z]);
687 z++;
688 }
689 strcat(t,"\n");
690 z=0;
691 for (i=0;i<ch;i++) {
692 while (!isalpha(ibuf[z])) z++;
693 sprintf(&t[strlen(t)]," %2d",toupper(ibuf[z]));
694 z++;
695 }
696 strcat(t," - as ASCII values\n");
697
698 z=0;
699 for (i=0;i<ch;i++) {
700 while (!isalpha(ibuf[z])) z++;
701 sprintf(&t[strlen(t)]," %d",simplify(toupper(ibuf[z])));
702 z++;
703 }
704 strcat(t," - digits added\n ");
705
706 for (i=0;i<ch;i++) {
707 int cur=i/(ch/4);
708 if (cur>4) cur=4;
709 if (pcur!=cur) {
710 if (pcur != -1) strcat(t,"/");
711 strcat(t," \\_");
712 } else strcat(t,"____");
713 pcur=cur;
714 }
715
716 strcat(t,"/\n");
717
718 for (i=0;i<ch;i++) {
719 int cur=i/(ch/4);
720 if (cur>4) cur=4;
721 if (pcur!=cur) sprintf(&t[strlen(t)]," %d",asum[cur]);
722 else strcat(t," ");
723 pcur=cur;
724 }
725
726 strcat(t," - digits added\n\n");
727
728 if (!asum[4])
729 p.val=asum[0]*1000+asum[1]*100+asum[2]*10+asum[3];
730 else
731 p.val=asum[0]*10000+asum[1]*1000+asum[2]*100+asum[3]*10+asum[4];
732
733 sprintf(&t[strlen(t)],"Thus, \"%s\" is %d.\n\n",ibuf,p.val);
734
735 p.prolog=strdup(t);
736 p.usednum[0]=p.val;p.utop=1;
737
738 trace_proof(&p);
739
740 }
741
742 alarm(0);
743
744 if (stopped) {
745 if (retrynum<5) goto retry;
746 fatal("System timeout.\n");
747 }
748
749
750 if (!restop) fatal("There is no way to prove the evilness of this!\n");
751
752 // Get random result
753
754 z=get_random() % restop;
755 printf("<b>**** THE PROOF THAT <i>%s</i> IS EVIL ****</b>\n<p>\n<pre>%s</pre>\n\n<p>%s\n",ibuf,rprolog[z],results[z]);
756
757 return 0;
758 }
759