Mercurial > repo
view src/ploki/main.c @ 8123:9df4aeaac079
<moon_> ` med il 1 \'lol this is a test\' testcmd
author | HackBot |
---|---|
date | Wed, 25 May 2016 00:31:41 +0000 |
parents | ac0403686959 |
children |
line wrap: on
line source
#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); }