/* main.c * * Andy Goth * * Derived from, and hopefully compatible with, GIMP's gqbist.c, originally by * Jens Ch. Restemeier . gqbist.c is available * under the GPL (GNU General Public License), version 2 or later. Therefore, * the file is also available under the GPL. And there was much rejoicing. */ #include #include #include #include "qbism.h" /* Allocates memory or else. */ void* xmalloc(size_t bytes) { void* result = malloc(bytes); if (result == NULL) { perror("malloc"); exit(EXIT_FAILURE); } return result; } /* Reallocates memory or else. */ void* xrealloc(void* buf, size_t bytes) { void* result = realloc(buf, bytes); if (result == NULL) { perror("realloc"); exit(EXIT_FAILURE); } return result; } typedef enum { OPT_INQBE, OPT_INQBM, OPT_OUTQBE, OPT_OUTQBM, OPT_OUTIMG, OPT_SIZE, OPT_REGS, OPT_STEPS, OPT_COUNT } opt_t; static char* opt_names[] = { "-inqbe", "-inqbm", "-outqbe", "-outqbm", "-outimg", "-size", "-regs", "-steps" }; static FILE* my_open(char* name, char* mode) { FILE* fd; if (strcmp(name, "-") == 0) { if (strcmp(mode, "r") == 0) { fd = stdin; } else { fd = stdout; } } else { fd = fopen(name, mode); if (fd == NULL) { perror(name); exit(EXIT_FAILURE); } } return fd; } static void my_close(FILE* fd) { if (fd != stdin && fd != stdout) { if (fclose(fd) == EOF) { perror("fclose"); exit(EXIT_FAILURE); } } } /* Repeals gravity. */ int main(int argc, char** argv) { FILE* fd; int width, height; int i, j; int split; algo_t algo = {NULL, 36, 12}; char* opts[OPT_COUNT] = {NULL}; /* Defaults. */ opts[OPT_SIZE] = "640x480"; opts[OPT_OUTIMG] = "-"; opts[OPT_REGS] = "6"; opts[OPT_STEPS] = "36"; /* Check if help is requested. */ if (argc > 1 && ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "-help") == 0) || (strcmp(argv[1], "--help") == 0))) { fprintf(stderr, "Usage: qbism [OPTION]...\n" "Use learning for evil.\n" "\n" " -inqbe FILE run the algorithm in the QBE FILE\n" " -inqbm FILE run the algorithm in the QBM FILE\n" " -outqbe FILE save the algorithm in QBE format to FILE\n" " -outqbm FILE save the algorithm in QBM format to FILE\n" " -outimg FILE render the image in MIFF format to FILE\n" " -size WIDTHxHEIGHT render at WIDTH by HEIGHT pixels\n" " -regs NUM for random algorithms, use NUM registers\n" " -steps NUM for random algorithms, use NUM steps\n" "\n" "If neither -inqbe nor -inqbm are specified, a random algorithm is\n" "generated and used to render the image. Otherwise the algorithm\n" "stored in the QBE or QBM file is used.\n" "\n" "Report features to Andy Goth .\n"); return EXIT_SUCCESS; } /* Check that every option has a parameter. */ if ((argc - 1) % 2 != 0) { fprintf(stderr, "Option \"%s\" has no parameter\n", argv[argc - 1]); return EXIT_FAILURE; } /* Get all parameters. */ for (i = 1; i < argc; i += 2) { for (j = 0; j < OPT_COUNT; ++j) { if (strcmp(argv[i], opt_names[j]) == 0) { opts[j] = argv[i + 1]; break; } } if (j == OPT_COUNT) { fprintf(stderr, "Unknown option \"%s\"\n", argv[i]); return EXIT_FAILURE; } } /* Check for disallowed combinations. */ if (opts[OPT_INQBE] != NULL && opts[OPT_INQBM] != NULL) { fprintf(stderr, "Cannot specify both -inqbe and -inqbm\n"); return EXIT_FAILURE; } /* Interpret numeric options. */ if (sscanf(opts[OPT_SIZE], "%dx%d", &width, &height) != 2) { fprintf(stderr, "Malformed size \"%s\"\n", opts[OPT_SIZE]); } if (sscanf(opts[OPT_REGS], "%d", &algo.num_regs) != 1 || algo.num_regs < 1) { fprintf(stderr, "Malformed register count \"%s\"\n", opts[OPT_REGS]); } if (sscanf(opts[OPT_STEPS], "%d", &algo.num_steps) != 1 || algo.num_steps < 0) { fprintf(stderr, "Malformed step count \"%s\"\n", opts[OPT_STEPS]); } /* Read/generate an algorithm. */ if (opts[OPT_INQBE] != NULL) { fd = my_open(opts[OPT_INQBE], "r"); algo_read_qbe(&algo, fd); my_close(fd); } else if (opts[OPT_INQBM] != NULL) { fprintf(stderr, "Unimplemented!\n"); } else { /* Generate a random transformation sequence. */ srandom(time(NULL)); algo.seq = xmalloc(sizeof(*algo.seq) * algo.num_steps); for (i = 0; i < algo.num_steps; ++i) { algo.seq[i].opcode = random() % XOP_COUNT; algo.seq[i].source = random() % algo.num_regs; algo.seq[i].control = random() % algo.num_regs; algo.seq[i].dest = random() % algo.num_regs; } } /* If so requested, write out the algorithm. */ if (opts[OPT_OUTQBE] != NULL) { fd = my_open(opts[OPT_OUTQBE], "w"); algo_write_qbe(&algo, fd); my_close(fd); } else if (opts[OPT_OUTQBM] != NULL) { fprintf(stderr, "Unimplemented!\n"); } /* Render! */ fd = my_open(opts[OPT_OUTIMG], "w"); qbism_render(&algo, width, height, fd); my_close(fd); return EXIT_SUCCESS; } /* vim: set ts=4 sts=4 sw=4 tw=80 et: */