Mercurial > repo
comparison 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 |
comparison
equal
deleted
inserted
replaced
4222:b0f3e267bb1e | 4223:ac0403686959 |
---|---|
1 #include "IO.h" | |
2 #include "Str.h" | |
3 #include "atechit.h" | |
4 #include "compile.h" | |
5 #include "deparse.h" | |
6 #include "expr.h" | |
7 #include "inc.h" | |
8 #include "main.h" | |
9 #include "main_io.h" | |
10 #include "main_label.h" | |
11 #include "main_opt.h" | |
12 #include "main_var.h" | |
13 #include "mars.h" | |
14 #include "opt.h" | |
15 #include "parse.h" | |
16 #include "random.h" | |
17 #include "re.h" | |
18 #include "run.h" | |
19 #include "text.h" | |
20 #include "transmogrify.h" | |
21 #include "val.h" | |
22 #include "venus.h" | |
23 #include "version.h" | |
24 #include "xmalloc.h" | |
25 #include "zz.h" | |
26 | |
27 #include <ctype.h> | |
28 #include <errno.h> | |
29 #include <math.h> | |
30 #include <stdio.h> | |
31 #include <stdlib.h> | |
32 #include <string.h> | |
33 | |
34 #define NAME "ploki" | |
35 #define WARN(x) fprintf(stderr, "%s: %s: %s\n", Prog, x, strerror(errno)) | |
36 | |
37 const char *Prog = NAME; | |
38 IO *In, *Out, *Err; | |
39 struct venus Venus; | |
40 struct mars Mars; | |
41 struct Options Opt; | |
42 t_vr_container *Var_plain, *Var_hash; | |
43 | |
44 static int my_mars_end_flag; | |
45 static void my_mars_end(void) { | |
46 if (!my_mars_end_flag) { | |
47 ma_end(&Mars); | |
48 } | |
49 } | |
50 | |
51 static void my_venus_end(void) { | |
52 ve_end(&Venus); | |
53 } | |
54 | |
55 static struct text text; | |
56 static void my_text_off(void) { | |
57 text_off(&text); | |
58 } | |
59 | |
60 static void xv_delete(void *v) { | |
61 v_delete(v); | |
62 } | |
63 | |
64 static void xsh_delete(void *sh) { | |
65 sh_delete(sh); | |
66 } | |
67 | |
68 static void var_end(void) { | |
69 if (Var_plain) { | |
70 vr_delete(Var_plain); | |
71 Var_plain = 0; | |
72 } | |
73 if (Var_hash) { | |
74 vr_delete(Var_hash); | |
75 Var_hash = 0; | |
76 } | |
77 } | |
78 | |
79 static char *s_lastof(const char *s, const char *set) { | |
80 const char *t = s + strlen(s); | |
81 while (t > s) { | |
82 --t; | |
83 if (strchr(set, *t)) { | |
84 return (char *)t; /* const correctness is for C++ programmers! */ | |
85 } | |
86 } | |
87 return NULL; | |
88 } | |
89 | |
90 static void usage(void) { | |
91 printf( | |
92 "Usage: %s [OPTIONS] [FILE [ARG]...]\n" | |
93 "\n" | |
94 "Available options:\n" | |
95 "\n" | |
96 " -h print a short help message and exit\n" | |
97 " -v print version and configuration info and exit\n" | |
98 " -MO=Deparse turn the compiled program back into ploki source\n" | |
99 " -O disable any optimizations\n" | |
100 " -d FLAGS print debugging info\n" | |
101 " FLAGS must be one or more of the following:\n" | |
102 " h hash tables\n" | |
103 " o opcode execution\n" | |
104 " r regex engine\n" | |
105 "\n" | |
106 "%s" | |
107 , Prog, | |
108 "Interpret FILE as ploki program and execute it, unless -MO=Deparse is\n" | |
109 "specified. With no FILE, or when FILE is -, read from standard input.\n" | |
110 "Any ARGs are passed through to the program.\n" | |
111 ); | |
112 } | |
113 | |
114 static void printinc(void) { | |
115 size_t i; | |
116 for (i = 0; inc_ludes[i]; ++i) { | |
117 printf(" \"%s\"", inc_ludes[i]); | |
118 } | |
119 } | |
120 | |
121 int main(int argc, char **argv) { | |
122 IO *f; | |
123 int c; | |
124 | |
125 if (argc > 0 && argv[0][0]) { | |
126 Prog = argv[0]; | |
127 } | |
128 | |
129 while ((c = opt_get(argc, argv, "-:?M:Od:hv")) != -1) { | |
130 switch (c) { | |
131 invalid_option: | |
132 fprintf(stderr, "%s: invalid option `%c'\n", Prog, c); | |
133 return EXIT_FAILURE; | |
134 | |
135 /* option aliasing */ | |
136 case '-': | |
137 if (!opt_arg) { | |
138 goto invalid_option; | |
139 } | |
140 if (!strncmp("help", opt_arg, strlen(opt_arg))) { | |
141 case 'h': | |
142 case '?': | |
143 usage(); | |
144 return EXIT_SUCCESS; | |
145 } | |
146 if (!strncmp("version", opt_arg, strlen(opt_arg))) { | |
147 case 'v': | |
148 printf( | |
149 "This is %s v%s\n" | |
150 "%cvsnprintf %csleep %c/dev/urandom %s%s %cM_PI %cM_E\nINC contains:", | |
151 NAME, | |
152 Version, | |
153 HAVE_VSNPRINTF_P ? '+' : '-', | |
154 HAVE_SLEEP_P ? '+' : '-', | |
155 HAVE_DEV_URANDOM_P ? '+' : '-', | |
156 DIR_END ? "+DIRSEP:" : "-DIRSEP", | |
157 DIR_END ? DIR_END : "", | |
158 #ifdef M_PI | |
159 '+' | |
160 #else | |
161 '-' | |
162 #endif | |
163 , | |
164 #ifdef M_E | |
165 '+' | |
166 #else | |
167 '-' | |
168 #endif | |
169 ); | |
170 printinc(); | |
171 fputs("\nWritten by Lukas Mai\n", stdout); | |
172 return EXIT_SUCCESS; | |
173 } | |
174 fprintf(stderr, "%s: invalid option `%s'\n", Prog, opt_arg); | |
175 return EXIT_FAILURE; | |
176 | |
177 case 'd': | |
178 if (!opt_arg || !opt_arg[0]) { | |
179 fprintf(stderr, "%s: option `%c' requires an argument\n", Prog, c); | |
180 return EXIT_FAILURE; | |
181 } else { | |
182 const char *a = opt_arg; | |
183 for (; *a; ++a) { | |
184 switch (*a) { | |
185 case 'h': Opt.debug |= DBG_HASH; break; | |
186 case 'o': Opt.debug |= DBG_OPS; break; | |
187 case 'r': Opt.debug |= DBG_REGEX; break; | |
188 default: | |
189 fprintf(stderr, "%s: option d's argument must be one of [hor], not `%s'\n", Prog, a); | |
190 return EXIT_FAILURE; | |
191 } | |
192 } | |
193 } | |
194 break; | |
195 | |
196 case 'M': | |
197 if (!opt_arg || strncmp(opt_arg, "O=Deparse", strlen(opt_arg))) { | |
198 goto invalid_option; | |
199 } | |
200 Opt.deparse = 1; | |
201 break; | |
202 | |
203 case 'O': | |
204 Opt.unoptimize = 1; | |
205 break; | |
206 | |
207 case '\0': | |
208 c = opt_err; | |
209 goto invalid_option; | |
210 | |
211 default: | |
212 NOTREACHED; | |
213 } | |
214 } | |
215 argc -= opt_ind; | |
216 argv += opt_ind; | |
217 | |
218 randseed(); | |
219 | |
220 atechit(xend); | |
221 io_init(); | |
222 atechit(io_end); | |
223 | |
224 In = io_enter("(stdin)", stdin, IO_READ | IO_BUFFERED); | |
225 Out = io_enter("(stdout)", stdout, IO_WRITE | IO_TRUNCATE | IO_AUTOFLUSH); | |
226 Err = io_enter("(stderr)", stderr, IO_WRITE | IO_TRUNCATE | IO_AUTOFLUSH); | |
227 | |
228 if (!argv[0] || (argv[0][0] == '-' && argv[0][1] == '\0')) { | |
229 f = io_incr(In); | |
230 } else { | |
231 if (!(f = io_open(argv[0], IO_READ | IO_BUFFERED))) { | |
232 WARN(argv[0]); | |
233 return EXIT_FAILURE; | |
234 } | |
235 } | |
236 | |
237 /* ignore empty files */ | |
238 { | |
239 size_t p; | |
240 for (p = 0; isspace(c = io_peek(f, p)); ++p) | |
241 ; | |
242 if (c == EOF) { | |
243 if (io_err(f)) { | |
244 WARN(io_name(f, NULL)); | |
245 io_decr(f); | |
246 return EXIT_FAILURE; | |
247 } else { | |
248 io_decr(f); | |
249 return EXIT_SUCCESS; | |
250 } | |
251 } | |
252 } | |
253 | |
254 re_init(); | |
255 atechit(re_end); | |
256 atechit(var_end); | |
257 Var_plain = vr_new(xv_delete); | |
258 Var_hash = vr_new(xsh_delete); | |
259 | |
260 text_on(&text); | |
261 atechit(my_text_off); | |
262 ma_init(&Mars); | |
263 atechit(my_mars_end); | |
264 ve_init(&Venus); | |
265 atechit(my_venus_end); | |
266 | |
267 { | |
268 size_t tmp = 0; | |
269 char *eop = NULL; | |
270 char bkp = 00; | |
271 if (argv[0]) { | |
272 if (DIR_END && (eop = s_lastof(argv[0], DIR_END))) { | |
273 size_t i; | |
274 bkp = eop[1]; | |
275 eop[1] = '\0'; | |
276 for (i = 0; inc_ludes[i]; ++i) { | |
277 if (inc_ludes[i][0] == '\0') { | |
278 inc_ludes[i] = argv[0]; | |
279 } | |
280 } | |
281 } | |
282 } | |
283 parse(f, &text, &tmp); | |
284 if (eop) { | |
285 eop[1] = bkp; | |
286 } | |
287 } | |
288 io_decr(f); | |
289 | |
290 expr_init(); | |
291 atechit(expr_end); | |
292 | |
293 compile(&text); | |
294 if (!Opt.unoptimize) { | |
295 transmogrify(&text); | |
296 } | |
297 | |
298 my_mars_end_flag = 1; | |
299 ma_end(&Mars); | |
300 | |
301 if (Opt.deparse) { | |
302 deparse(&text); | |
303 return 0; | |
304 } | |
305 | |
306 run(&text, argc, argv); | |
307 } |