Mercurial > repo
diff src/ploki/main.c @ 4223:ac0403686959
<oerjan> rm -rf src/ploki; mv ploki src
author | HackBot |
---|---|
date | Fri, 20 Dec 2013 22:18:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ploki/main.c Fri Dec 20 22:18:50 2013 +0000 @@ -0,0 +1,307 @@ +#include "IO.h" +#include "Str.h" +#include "atechit.h" +#include "compile.h" +#include "deparse.h" +#include "expr.h" +#include "inc.h" +#include "main.h" +#include "main_io.h" +#include "main_label.h" +#include "main_opt.h" +#include "main_var.h" +#include "mars.h" +#include "opt.h" +#include "parse.h" +#include "random.h" +#include "re.h" +#include "run.h" +#include "text.h" +#include "transmogrify.h" +#include "val.h" +#include "venus.h" +#include "version.h" +#include "xmalloc.h" +#include "zz.h" + +#include <ctype.h> +#include <errno.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define NAME "ploki" +#define WARN(x) fprintf(stderr, "%s: %s: %s\n", Prog, x, strerror(errno)) + +const char *Prog = NAME; +IO *In, *Out, *Err; +struct venus Venus; +struct mars Mars; +struct Options Opt; +t_vr_container *Var_plain, *Var_hash; + +static int my_mars_end_flag; +static void my_mars_end(void) { + if (!my_mars_end_flag) { + ma_end(&Mars); + } +} + +static void my_venus_end(void) { + ve_end(&Venus); +} + +static struct text text; +static void my_text_off(void) { + text_off(&text); +} + +static void xv_delete(void *v) { + v_delete(v); +} + +static void xsh_delete(void *sh) { + sh_delete(sh); +} + +static void var_end(void) { + if (Var_plain) { + vr_delete(Var_plain); + Var_plain = 0; + } + if (Var_hash) { + vr_delete(Var_hash); + Var_hash = 0; + } +} + +static char *s_lastof(const char *s, const char *set) { + const char *t = s + strlen(s); + while (t > s) { + --t; + if (strchr(set, *t)) { + return (char *)t; /* const correctness is for C++ programmers! */ + } + } + return NULL; +} + +static void usage(void) { + printf( + "Usage: %s [OPTIONS] [FILE [ARG]...]\n" + "\n" + "Available options:\n" + "\n" + " -h print a short help message and exit\n" + " -v print version and configuration info and exit\n" + " -MO=Deparse turn the compiled program back into ploki source\n" + " -O disable any optimizations\n" + " -d FLAGS print debugging info\n" + " FLAGS must be one or more of the following:\n" + " h hash tables\n" + " o opcode execution\n" + " r regex engine\n" + "\n" + "%s" + , Prog, + "Interpret FILE as ploki program and execute it, unless -MO=Deparse is\n" + "specified. With no FILE, or when FILE is -, read from standard input.\n" + "Any ARGs are passed through to the program.\n" + ); +} + +static void printinc(void) { + size_t i; + for (i = 0; inc_ludes[i]; ++i) { + printf(" \"%s\"", inc_ludes[i]); + } +} + +int main(int argc, char **argv) { + IO *f; + int c; + + if (argc > 0 && argv[0][0]) { + Prog = argv[0]; + } + + while ((c = opt_get(argc, argv, "-:?M:Od:hv")) != -1) { + switch (c) { +invalid_option: + fprintf(stderr, "%s: invalid option `%c'\n", Prog, c); + return EXIT_FAILURE; + + /* option aliasing */ + case '-': + if (!opt_arg) { + goto invalid_option; + } + if (!strncmp("help", opt_arg, strlen(opt_arg))) { + case 'h': + case '?': + usage(); + return EXIT_SUCCESS; + } + if (!strncmp("version", opt_arg, strlen(opt_arg))) { + case 'v': + printf( + "This is %s v%s\n" + "%cvsnprintf %csleep %c/dev/urandom %s%s %cM_PI %cM_E\nINC contains:", + NAME, + Version, + HAVE_VSNPRINTF_P ? '+' : '-', + HAVE_SLEEP_P ? '+' : '-', + HAVE_DEV_URANDOM_P ? '+' : '-', + DIR_END ? "+DIRSEP:" : "-DIRSEP", + DIR_END ? DIR_END : "", + #ifdef M_PI + '+' + #else + '-' + #endif + , + #ifdef M_E + '+' + #else + '-' + #endif + ); + printinc(); + fputs("\nWritten by Lukas Mai\n", stdout); + return EXIT_SUCCESS; + } + fprintf(stderr, "%s: invalid option `%s'\n", Prog, opt_arg); + return EXIT_FAILURE; + + case 'd': + if (!opt_arg || !opt_arg[0]) { + fprintf(stderr, "%s: option `%c' requires an argument\n", Prog, c); + return EXIT_FAILURE; + } else { + const char *a = opt_arg; + for (; *a; ++a) { + switch (*a) { + case 'h': Opt.debug |= DBG_HASH; break; + case 'o': Opt.debug |= DBG_OPS; break; + case 'r': Opt.debug |= DBG_REGEX; break; + default: + fprintf(stderr, "%s: option d's argument must be one of [hor], not `%s'\n", Prog, a); + return EXIT_FAILURE; + } + } + } + break; + + case 'M': + if (!opt_arg || strncmp(opt_arg, "O=Deparse", strlen(opt_arg))) { + goto invalid_option; + } + Opt.deparse = 1; + break; + + case 'O': + Opt.unoptimize = 1; + break; + + case '\0': + c = opt_err; + goto invalid_option; + + default: + NOTREACHED; + } + } + argc -= opt_ind; + argv += opt_ind; + + randseed(); + + atechit(xend); + io_init(); + atechit(io_end); + + In = io_enter("(stdin)", stdin, IO_READ | IO_BUFFERED); + Out = io_enter("(stdout)", stdout, IO_WRITE | IO_TRUNCATE | IO_AUTOFLUSH); + Err = io_enter("(stderr)", stderr, IO_WRITE | IO_TRUNCATE | IO_AUTOFLUSH); + + if (!argv[0] || (argv[0][0] == '-' && argv[0][1] == '\0')) { + f = io_incr(In); + } else { + if (!(f = io_open(argv[0], IO_READ | IO_BUFFERED))) { + WARN(argv[0]); + return EXIT_FAILURE; + } + } + + /* ignore empty files */ + { + size_t p; + for (p = 0; isspace(c = io_peek(f, p)); ++p) + ; + if (c == EOF) { + if (io_err(f)) { + WARN(io_name(f, NULL)); + io_decr(f); + return EXIT_FAILURE; + } else { + io_decr(f); + return EXIT_SUCCESS; + } + } + } + + re_init(); + atechit(re_end); + atechit(var_end); + Var_plain = vr_new(xv_delete); + Var_hash = vr_new(xsh_delete); + + text_on(&text); + atechit(my_text_off); + ma_init(&Mars); + atechit(my_mars_end); + ve_init(&Venus); + atechit(my_venus_end); + + { + size_t tmp = 0; + char *eop = NULL; + char bkp = 00; + if (argv[0]) { + if (DIR_END && (eop = s_lastof(argv[0], DIR_END))) { + size_t i; + bkp = eop[1]; + eop[1] = '\0'; + for (i = 0; inc_ludes[i]; ++i) { + if (inc_ludes[i][0] == '\0') { + inc_ludes[i] = argv[0]; + } + } + } + } + parse(f, &text, &tmp); + if (eop) { + eop[1] = bkp; + } + } + io_decr(f); + + expr_init(); + atechit(expr_end); + + compile(&text); + if (!Opt.unoptimize) { + transmogrify(&text); + } + + my_mars_end_flag = 1; + ma_end(&Mars); + + if (Opt.deparse) { + deparse(&text); + return 0; + } + + run(&text, argc, argv); +}