RPA Toolkit
a9957bd8713dbca94a87f71bd3ba046a707c61a4
[rpatk.git] / rjs / rjsexec.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <sys/types.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 #include <sys/mman.h>
9
10 #include "rstring.h"
11 #include "rmem.h"
12 #include "rjs.h"
13 #include "rparecord.h"
14
15
16 static int debuginfo = 0;
17 static int parseinfo = 0;
18 static int compileonly = 0;
19 static int debugcompileonly = 0;
20 static int statinfo = 0;
21
22
23 static rchar *errormsg[] = {
24         "OK",
25         "Undefined identifier",
26         "Syntax error",
27         "Not a function",
28         "Not a function call",
29         "Not a loop",
30         "Not a if statement",
31         "Unknown",
32         "Unknown",
33         "Unknown",
34         "Unknown",
35         "Unknown",
36         "Unknown",
37         "Unknown",
38         "Unknown",
39         "Unknown",
40         "Unknown",
41 };
42
43
44 static void rjs_exec_ltrim(rvmcpu_t *cpu, rvm_asmins_t *ins)
45 {
46         const rchar *ptr, *list;
47         rsize_t size;
48         rvmreg_t *r = NULL, *l = NULL;
49         rstring_t *src, *dest;
50
51         if (RJS_SWI_PARAMS(cpu) == 0) {
52                 rjs_engine_abort(rjs_engine_get(cpu), NULL);
53                 return;
54         }
55         r = (rvmreg_t *) RJS_SWI_PARAM(cpu, 1);
56         if (RJS_SWI_PARAMS(cpu) > 1) {
57                 l = (rvmreg_t *) RJS_SWI_PARAM(cpu, 2);
58                 if (rvm_reg_gettype(l) != RVM_DTYPE_STRING) {
59                         rjs_engine_abort(rjs_engine_get(cpu), NULL);
60                         return;
61                 }
62         }
63         if (rvm_reg_gettype(r) != RVM_DTYPE_STRING) {
64                 rjs_engine_abort(rjs_engine_get(cpu), NULL);
65                 return;
66         }
67
68         if (l)
69                 list = ((rstring_t *)RVM_REG_GETP(l))->s.str;
70         else
71                 list = " \t\n\r\0";
72         src = (rstring_t *)RVM_REG_GETP(r);
73         ptr = src->s.str;
74         size = src->s.size;
75         while (size > 0) {
76                 if (!r_strchr(list, *ptr))
77                         break;
78                 size--;
79                 ptr++;
80         }
81         dest = r_string_create_strsize(ptr, size);
82         rvm_gc_add(cpu->gc, (robject_t*)dest);
83         rvm_reg_setstring(RVM_CPUREG_PTR(cpu, R0), dest);
84 }
85
86
87 static void rjs_exec_rtrim(rvmcpu_t *cpu, rvm_asmins_t *ins)
88 {
89         const rchar *ptr, *list;
90         rsize_t size;
91         rvmreg_t *r = NULL, *l = NULL;
92         rstring_t *src, *dest;
93
94         if (RJS_SWI_PARAMS(cpu) == 0) {
95                 rjs_engine_abort(rjs_engine_get(cpu), NULL);
96                 return;
97         }
98         r = (rvmreg_t *) RJS_SWI_PARAM(cpu, 1);
99         if (RJS_SWI_PARAMS(cpu) > 1) {
100                 l = (rvmreg_t *) RJS_SWI_PARAM(cpu, 2);
101                 if (rvm_reg_gettype(l) != RVM_DTYPE_STRING) {
102                         rjs_engine_abort(rjs_engine_get(cpu), NULL);
103                         return;
104                 }
105         }
106         if (rvm_reg_gettype(r) != RVM_DTYPE_STRING) {
107                 rjs_engine_abort(rjs_engine_get(cpu), NULL);
108                 return;
109         }
110
111         if (l)
112                 list = ((rstring_t *)RVM_REG_GETP(l))->s.str;
113         else
114                 list = " \t\n\r\0";
115         src = (rstring_t *)RVM_REG_GETP(r);
116         size = src->s.size;
117         ptr = src->s.str + size - 1;
118         while (size > 0) {
119                 if (!r_strchr(list, *ptr))
120                         break;
121                 size--;
122                 ptr--;
123         }
124         dest = r_string_create_strsize(src->s.str, size);
125         rvm_gc_add(cpu->gc, (robject_t*)dest);
126         rvm_reg_setstring(RVM_CPUREG_PTR(cpu, R0), dest);
127 }
128
129
130 static void rjs_exec_trim(rvmcpu_t *cpu, rvm_asmins_t *ins)
131 {
132         const rchar *start, *ptr, *list;
133         rsize_t size;
134         rvmreg_t *r = NULL, *l = NULL;
135         rstring_t *src, *dest;
136
137         if (RJS_SWI_PARAMS(cpu) == 0) {
138                 rjs_engine_abort(rjs_engine_get(cpu), NULL);
139                 return;
140         }
141         r = (rvmreg_t *) RJS_SWI_PARAM(cpu, 1);
142         if (RJS_SWI_PARAMS(cpu) > 1) {
143                 l = (rvmreg_t *) RJS_SWI_PARAM(cpu, 2);
144                 if (rvm_reg_gettype(l) != RVM_DTYPE_STRING) {
145                         rjs_engine_abort(rjs_engine_get(cpu), NULL);
146                         return;
147                 }
148         }
149         if (rvm_reg_gettype(r) != RVM_DTYPE_STRING) {
150                 rjs_engine_abort(rjs_engine_get(cpu), NULL);
151                 return;
152         }
153
154         if (l)
155                 list = ((rstring_t *)RVM_REG_GETP(l))->s.str;
156         else
157                 list = " \t\n\r\0";
158         src = (rstring_t *)RVM_REG_GETP(r);
159         ptr = src->s.str;
160         size = src->s.size;
161         while (size > 0) {
162                 if (!r_strchr(list, *ptr))
163                         break;
164                 size--;
165                 ptr++;
166         }
167         start = ptr;
168         ptr = start + size - 1;
169         while (size > 0) {
170                 if (!r_strchr(list, *ptr))
171                         break;
172                 size--;
173                 ptr--;
174         }
175         dest = r_string_create_strsize(start, size);
176         rvm_gc_add(cpu->gc, (robject_t*)dest);
177         rvm_reg_setstring(RVM_CPUREG_PTR(cpu, R0), dest);
178 }
179
180
181 static rvm_switable_t swistring[] = {
182                 {"ltrim", rjs_exec_ltrim},
183                 {"rtrim", rjs_exec_rtrim},
184                 {"trim", rjs_exec_trim},
185                 {NULL, NULL},
186 };
187
188
189 void rjs_unmap_file(rstr_t *buf)
190 {
191         if (buf) {
192                 munmap(buf->str, buf->size);
193                 r_free(buf);
194         }
195 }
196
197
198 rstr_t *rjs_map_file(const char *filename)
199 {
200         struct stat st;
201         rstr_t *str;
202         char *buffer;
203
204
205         int fd = open(filename, O_RDONLY);
206         if (fd < 0) {
207                 return (void*)0;
208         }
209         if (fstat(fd, &st) < 0) {
210                 close(fd);
211                 return (void*)0;
212         }
213         buffer = (char*)mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
214         if (buffer == (void*)-1) {
215                 close(fd);
216                 return (void*)0;
217         }
218         str = (rstr_t *)r_malloc(sizeof(*str));
219         if (!str)
220                 goto error;
221         r_memset(str, 0, sizeof(*str));
222         str->str = buffer;
223         str->size = st.st_size;
224         close(fd);
225         return str;
226
227 error:
228         munmap(buffer, st.st_size);
229         close(fd);
230         return str;
231 }
232
233
234 int rjs_exec_script(rjs_engine_t *jse, rstr_t  *script)
235 {
236         if (!script)
237                 return -1;
238         if (parseinfo) {
239                 rjs_engine_dumpast(jse, script->str, script->size);
240         } else if (debugcompileonly) {
241                 int res = 0;
242                 jse->debugcompile = 1;
243                 res = rjs_engine_compile(jse, script->str, script->size);
244                 jse->debugcompile = 0;
245                 if (res < 0)
246                         return -1;
247         } else if (compileonly) {
248                 if (rjs_engine_compile(jse, script->str, script->size) < 0)
249                         return -1;
250         } else {
251                 if (rjs_engine_compile(jse, script->str, script->size) < 0)
252                         return -1;
253                 if (rjs_engine_run(jse) < 0)
254                         return -1;
255         }
256
257         return 0;
258 }
259
260
261 rlong jrs_offset2line(const rchar *script, rlong offset)
262 {
263         rlong line = 0;
264         const rchar *ptr;
265
266         for (line = 1, ptr = script + offset; ptr >= script; --ptr) {
267                 if (*ptr == '\n')
268                         line += 1;
269         }
270
271         return line;
272 }
273
274
275 void rjs_display_errors(rjs_engine_t *jse, rstr_t *script)
276 {
277         rlong i;
278         rjs_error_t *err;
279
280         for (i = 0; i < r_array_length(jse->errors); i++) {
281                 err = (rjs_error_t *)r_array_slot(jse->errors, i);
282                 fprintf(stdout, "Line: %ld (%ld, %ld), Error Code: %ld, ", (rlong)err->line, err->offset, err->lineoffset, err->error);
283                 fprintf(stdout, "%s: ", errormsg[err->error]);
284                 if (err->size) {
285                         fwrite(script->str + err->offset, sizeof(rchar), err->size, stdout);
286                 } else {
287                         fwrite(script->str + err->lineoffset, sizeof(rchar), err->offset - err->lineoffset, stdout);
288                 }
289                 fprintf(stdout, "\n");
290         }
291 }
292
293
294 int main(int argc, char *argv[])
295 {
296         rint i;
297         rstr_t *script = NULL, *unmapscript = NULL;
298         rstr_t line;
299         rjs_engine_t *jse;
300
301         jse = rjs_engine_create();
302         if (!jse)
303                 return 1;
304         if (rjs_engine_addswitable(jse, "string", swistring) < 0) {
305                 return 2;
306         }
307         for (i = 1; i < argc; i++) {
308                 if (r_strcmp(argv[i], "-L") == 0) {
309
310                 } else if (r_strcmp(argv[i], "-d") == 0) {
311                         debuginfo = 1;
312                         jse->debugexec = 1;
313                 } else if (r_strcmp(argv[i], "-p") == 0) {
314                         parseinfo = 1;
315                 } else if (r_strcmp(argv[i], "-C") == 0) {
316                         debugcompileonly = 1;
317                 } else if (r_strcmp(argv[i], "-c") == 0) {
318                         compileonly = 1;
319                 } else if (r_strcmp(argv[i], "-t") == 0) {
320                         statinfo = 1;
321                 }
322         }
323
324         for (i = 1; i < argc; i++) {
325                 if (r_strcmp(argv[i], "-e") == 0) {
326                         if (++i < argc) {
327                                 line.str = argv[i];
328                                 line.size = r_strlen(argv[i]);
329                                 script = &line;
330                         }
331                         if (rjs_exec_script(jse, script) < 0)
332                                 goto end;
333                 }
334         }
335
336         for (i = 1; i < argc; i++) {
337                 if (r_strcmp(argv[i], "-f") == 0) {
338                         if (++i < argc) {
339                                 script = rjs_map_file(argv[i]);
340                                 if (script) {
341                                         unmapscript = script;
342                                 }
343                         }
344                         if (rjs_exec_script(jse, script) < 0)
345                                 goto end;
346                 }
347         }
348
349 end:
350         if (jse && r_array_length(jse->errors))
351                 rjs_display_errors(jse, script);
352         rjs_engine_destroy(jse);
353         if (unmapscript)
354                 rjs_unmap_file(unmapscript);
355         if (statinfo)
356                 fprintf(stdout, "\nRJS Version: %s, memory: %ld Bytes (leaked %ld Bytes)\n", rjs_version(), (rlong)r_debug_get_maxmem(), (rlong)r_debug_get_allocmem());
357         return 0;
358 }