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