]> git.proxmox.com Git - ceph.git/blob - ceph/src/civetweb/src/third_party/duktape-1.8.0/examples/eventloop/main.c
buildsys: switch source download to quincy
[ceph.git] / ceph / src / civetweb / src / third_party / duktape-1.8.0 / examples / eventloop / main.c
1 /*
2 * Main for evloop command line tool.
3 *
4 * Runs a given script from file or stdin inside an eventloop. The
5 * script can then access setTimeout() etc.
6 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #ifndef NO_SIGNAL
12 #include <signal.h>
13 #endif
14
15 #include "duktape.h"
16
17 extern void poll_register(duk_context *ctx);
18 extern void ncurses_register(duk_context *ctx);
19 extern void socket_register(duk_context *ctx);
20 extern void fileio_register(duk_context *ctx);
21 extern void eventloop_register(duk_context *ctx);
22 extern int eventloop_run(duk_context *ctx); /* Duktape/C function, safe called */
23
24 static int c_evloop = 0;
25
26 #ifndef NO_SIGNAL
27 static void my_sighandler(int x) {
28 fprintf(stderr, "Got signal %d\n", x);
29 fflush(stderr);
30 }
31 static void set_sigint_handler(void) {
32 (void) signal(SIGINT, my_sighandler);
33 }
34 #endif /* NO_SIGNAL */
35
36 /* Print error to stderr and pop error. */
37 static void print_error(duk_context *ctx, FILE *f) {
38 if (duk_is_object(ctx, -1) && duk_has_prop_string(ctx, -1, "stack")) {
39 /* XXX: print error objects specially */
40 /* XXX: pcall the string coercion */
41 duk_get_prop_string(ctx, -1, "stack");
42 if (duk_is_string(ctx, -1)) {
43 fprintf(f, "%s\n", duk_get_string(ctx, -1));
44 fflush(f);
45 duk_pop_2(ctx);
46 return;
47 } else {
48 duk_pop(ctx);
49 }
50 }
51 duk_to_string(ctx, -1);
52 fprintf(f, "%s\n", duk_get_string(ctx, -1));
53 fflush(f);
54 duk_pop(ctx);
55 }
56
57 int wrapped_compile_execute(duk_context *ctx) {
58 int comp_flags = 0;
59 int rc;
60
61 /* Compile input and place it into global _USERCODE */
62 duk_compile(ctx, comp_flags);
63 duk_push_global_object(ctx);
64 duk_insert(ctx, -2); /* [ ... global func ] */
65 duk_put_prop_string(ctx, -2, "_USERCODE");
66 duk_pop(ctx);
67 #if 0
68 printf("compiled usercode\n");
69 #endif
70
71 /* Start a zero timer which will call _USERCODE from within
72 * the event loop.
73 */
74 fprintf(stderr, "set _USERCODE timer\n");
75 fflush(stderr);
76 duk_eval_string(ctx, "setTimeout(function() { _USERCODE(); }, 0);");
77 duk_pop(ctx);
78
79 /* Finally, launch eventloop. This call only returns after the
80 * eventloop terminates.
81 */
82 if (c_evloop) {
83 fprintf(stderr, "calling eventloop_run()\n");
84 fflush(stderr);
85 rc = duk_safe_call(ctx, eventloop_run, 0 /*nargs*/, 1 /*nrets*/);
86 if (rc != 0) {
87 fprintf(stderr, "eventloop_run() failed: %s\n", duk_to_string(ctx, -1));
88 fflush(stderr);
89 }
90 duk_pop(ctx);
91 } else {
92 fprintf(stderr, "calling EventLoop.run()\n");
93 fflush(stderr);
94 duk_eval_string(ctx, "EventLoop.run();");
95 duk_pop(ctx);
96 }
97
98 return 0;
99 }
100
101 int handle_fh(duk_context *ctx, FILE *f, const char *filename) {
102 char *buf = NULL;
103 int len;
104 int got;
105 int rc;
106 int retval = -1;
107
108 if (fseek(f, 0, SEEK_END) < 0) {
109 goto error;
110 }
111 len = (int) ftell(f);
112 if (fseek(f, 0, SEEK_SET) < 0) {
113 goto error;
114 }
115 buf = (char *) malloc(len);
116 if (!buf) {
117 goto error;
118 }
119
120 got = fread((void *) buf, (size_t) 1, (size_t) len, f);
121
122 duk_push_lstring(ctx, buf, got);
123 duk_push_string(ctx, filename);
124
125 free(buf);
126 buf = NULL;
127
128 rc = duk_safe_call(ctx, wrapped_compile_execute, 2 /*nargs*/, 1 /*nret*/);
129 if (rc != DUK_EXEC_SUCCESS) {
130 print_error(ctx, stderr);
131 goto error;
132 } else {
133 duk_pop(ctx);
134 retval = 0;
135 }
136 /* fall thru */
137
138 error:
139 if (buf) {
140 free(buf);
141 }
142 return retval;
143 }
144
145 int handle_file(duk_context *ctx, const char *filename) {
146 FILE *f = NULL;
147 int retval;
148
149 f = fopen(filename, "rb");
150 if (!f) {
151 fprintf(stderr, "failed to open source file: %s\n", filename);
152 fflush(stderr);
153 goto error;
154 }
155
156 retval = handle_fh(ctx, f, filename);
157
158 fclose(f);
159 return retval;
160
161 error:
162 return -1;
163 }
164
165 int handle_stdin(duk_context *ctx) {
166 int retval;
167
168 retval = handle_fh(ctx, stdin, "stdin");
169
170 return retval;
171 }
172
173 int main(int argc, char *argv[]) {
174 duk_context *ctx = NULL;
175 int retval = 0;
176 const char *filename = NULL;
177 int i;
178
179 #ifndef NO_SIGNAL
180 set_sigint_handler();
181
182 /* This is useful at the global level; libraries should avoid SIGPIPE though */
183 /*signal(SIGPIPE, SIG_IGN);*/
184 #endif
185
186 for (i = 1; i < argc; i++) {
187 char *arg = argv[i];
188 if (!arg) {
189 goto usage;
190 }
191 if (strcmp(arg, "-c") == 0) {
192 c_evloop = 1;
193 } else if (strlen(arg) > 1 && arg[0] == '-') {
194 goto usage;
195 } else {
196 if (filename) {
197 goto usage;
198 }
199 filename = arg;
200 }
201 }
202 if (!filename) {
203 goto usage;
204 }
205
206 ctx = duk_create_heap_default();
207
208 poll_register(ctx);
209 ncurses_register(ctx);
210 socket_register(ctx);
211 fileio_register(ctx);
212
213 if (c_evloop) {
214 fprintf(stderr, "Using C based eventloop (omit -c to use Ecmascript based eventloop)\n");
215 fflush(stderr);
216
217 eventloop_register(ctx);
218 duk_eval_file(ctx, "c_eventloop.js");
219 } else {
220 fprintf(stderr, "Using Ecmascript based eventloop (give -c to use C based eventloop)\n");
221 fflush(stderr);
222
223 duk_eval_file(ctx, "ecma_eventloop.js");
224 }
225
226 fprintf(stderr, "Executing code from: '%s'\n", filename);
227 fflush(stderr);
228
229 if (strcmp(filename, "-") == 0) {
230 if (handle_stdin(ctx) != 0) {
231 retval = 1;
232 goto cleanup;
233 }
234 } else {
235 if (handle_file(ctx, filename) != 0) {
236 retval = 1;
237 goto cleanup;
238 }
239 }
240
241 cleanup:
242 if (ctx) {
243 duk_destroy_heap(ctx);
244 }
245
246 return retval;
247
248 usage:
249 fprintf(stderr, "Usage: evloop [-c] <filename>\n");
250 fprintf(stderr, "\n");
251 fprintf(stderr, "Uses an Ecmascript based eventloop (ecma_eventloop.js) by default.\n");
252 fprintf(stderr, "If -c option given, uses a C based eventloop (c_eventloop.{c,js}).\n");
253 fprintf(stderr, "If <filename> is '-', the entire STDIN executed.\n");
254 fflush(stderr);
255 exit(1);
256 }