#include #include #include #include #include #include #include "evil.h" static char *txtfile = NULL; void printOp(operator_t op) { switch(op) { case(ADD): printf("+"); break; case(SUB): printf("-"); break; case(MUL): printf("*"); break; case(DIV): printf("/"); break; case(PAL): printf("pal"); break; default: printf("???"); } } bool printEvil(uint32_t number) { /* We open the file for each iteration, but there's ~2 iterations, so it's fine */ FILE *file = NULL; if (NULL != txtfile) { file = fopen(txtfile, "r"); } else { file = fopen("evil.txt", "r"); } if (NULL == file) { perror("Error opening txt file"); return false; } char line[1024]; while (fgets(line, sizeof(line), file)) { if (atoi(line) == number) { char *reason = strchr(line, ' '); if (0 == reason) { printf("an illegal number: malformed txt file!\n"); return false; } /* Remove the newline at the end, Windows users are in for a surprise */ reason[strlen(reason)-1] = '\0'; /* Remove the space at the beginning */ printf("%s", reason+1); break; } } fclose(file); return true; } /* Decode an entry in evilDb */ void decodeEntry(uint32_t value, uint64_t *db) { uint64_t entry = db[value]; uint32_t parent = (uint32_t) (entry >> 32); operator_t operator = (operator_t) ((entry >> INDEXBITS) & 7); uint32_t ref = entry & INDEXMASK; if (0 == operator) { printf("%d is not in the database\n", value); } else if (PAL == operator) { printf("%d is %d reversed\n", value, parent); } else if (0 != parent) { printf("%d = %d ", value, parent); printOp(operator); printf(" %d (", ref); if (!(printEvil(ref))) { free(db); exit(42); } printf(")\n"); } else { printf("%d is ", ref); if (!(printEvil(ref))) { free(db); exit(42); } printf(".\n"); } } /* Print proof of evilness for value */ void find(uint32_t value, uint64_t *db) { while (0 != value) { decodeEntry(value, db); uint64_t entry = db[value]; value = (uint32_t) (entry >> 32); } } int main(int argc, char *argv[]) { char *dbfile = NULL; uint64_t *db = NULL; int number = 0; bool first = true; for (int i = 1; i 4) && (strcmp(argv[i] + len - 4, ".txt") == 0)) { txtfile = argv[i]; printf("Using %s for reference.\n", txtfile); } else if ((len > 3) && (strcmp(argv[i] + len - 3, ".db") == 0)) { dbfile = argv[i]; printf("Using %s as database.\n", dbfile); } else { // Attempt to convert string to number bool isNumber = true; for (int j=0; j ord) { // pass } else if ('9' >= ord) { digit = ord - '0'; } else if ('A' > ord) { // pass } else if ('Z' >= ord) { digit = ord - 'A' + 1; } else if ('a' > ord) { // pass } else if ('z' >= ord) { digit = ord - 'a' + 1; } number += digit; if (first) { printf(" %02d ", digit); first = false; } else { printf("+ %02d ", digit); } } printf(" = %d\n", number); } printf("\n"); } } if (0 == number) { printf("Usage: %s 668\n", argv[0]); exit(0); } // Load database FILE *fp = NULL; if(NULL != dbfile) { fp = fopen(dbfile, "rb"); } else { fp = fopen("evil.db", "rb"); } if (NULL == fp) { perror("fopen"); exit(1); } fseek(fp, 0, SEEK_END); int size = ftell(fp); fseek(fp, 0, SEEK_SET); if (0 != (size & 0x3)) { fclose(fp); printf("Database malformed\n"); exit(10); } if ((number > size) || number < 0) { printf("%d is not in the database!\n", number); } else { db = (uint64_t*) malloc(size); size /= sizeof(uint64_t); size_t read = fread(db, sizeof(uint64_t), size, fp); fclose(fp); if (size != read) { printf("Database size was %d, expected %d\n", (int) read, size); perror("fread"); free(db); exit(2); } find(number, db); free(db); } printf("Coincidence? I think not!\n"); exit(0); }