RPA Toolkit
work on RPA2 ALT expressions
[rpatk.git] / tests / regex-test.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 #include "rvmcodegen.h"
10 #include "rvmscope.h"
11 #include "rvmcpu.h"
12 #include "rmem.h"
13 #include "rutf.h"
14
15
16 static ruint regextable;
17 static int debuginfo = 0;
18 static int parseinfo = 0;
19 static int compileonly = 0;
20
21 #define RPA_RECORD_NONE (0)
22 #define RPA_RECORD_START (1 << 0)
23 #define RPA_RECORD_END (1 << 1)
24 #define RPA_RECORD_MATCH (1 << 2)
25
26 #define RPA_MATCH_NONE 0
27 #define RPA_MATCH_MULTIPLE (1 << 0)
28 #define RPA_MATCH_OPTIONAL (1 << 1)
29 #define RPA_MATCH_MULTIOPT (RPA_MATCH_MULTIPLE | RPA_MATCH_OPTIONAL)
30 #define R_FLG R7
31 #define R_ARG R8
32 #define R_WHT FP
33 #define R_TOP TP
34
35
36
37 #define R_MNODE_NAN R4
38 #define R_MNODE_MUL R5
39 #define R_MNODE_OPT R6
40 #define R_MNODE_MOP R7
41
42
43 #define RPA_MATCHCHR_NAN        RVM_OPSWI(RVM_SWI_ID(regextable, 0))
44 #define RPA_MATCHCHR_OPT        RVM_OPSWI(RVM_SWI_ID(regextable, 1))
45 #define RPA_MATCHCHR_MUL        RVM_OPSWI(RVM_SWI_ID(regextable, 2))
46 #define RPA_MATCHCHR_MOP        RVM_OPSWI(RVM_SWI_ID(regextable, 3))
47 #define RPA_SHIFT                       RVM_OPSWI(RVM_SWI_ID(regextable, 4))
48 #define RPA_EQSHIFT                     RVM_OPSWI(RVM_SWI_ID(regextable, 5))
49 #define RPA_NEQSHIFT            RVM_OPSWI(RVM_SWI_ID(regextable, 6))
50 #define RPA_EMITSTART           RVM_OPSWI(RVM_SWI_ID(regextable, 7))
51 #define RPA_EMITEND                     RVM_OPSWI(RVM_SWI_ID(regextable, 8))
52 #define RPA_MATCHANY_NAN        RVM_OPSWI(RVM_SWI_ID(regextable, 9))
53 #define RPA_MATCHEOL_NAN        RVM_OPSWI(RVM_SWI_ID(regextable, 10))
54 #define RPA_BXLWHT                      RVM_OPSWI(RVM_SWI_ID(regextable, 11))
55
56
57 typedef struct rpa_compiler_s {
58         rvm_codegen_t *cg;
59         rboolean optimized;
60         rvm_scope_t *scope;
61         rulong fpoff;
62 } rpa_compiler_t;
63
64
65 typedef struct rparecord_s {
66         rlist_t head;
67         rlink_t lnk;
68         const char *rule;
69         rword top;
70         rword size;
71         rword type;
72 } rparecord_t;
73
74
75 typedef struct rpainput_s {
76         const rchar *input;
77         ruint32 wc;
78         ruchar eof;
79 } rpainput_t;
80
81
82 typedef struct rpainmap_s {
83         const rchar *input;
84         rulong serial;
85 } rpainmap_t;
86
87
88 typedef struct rpastat_s {
89         const rchar *input;
90         const rchar *start;
91         const rchar *end;
92         ruint error;
93         rarray_t *records;
94         rpainput_t *instack;
95         rulong instacksize;
96         rulong cursize;
97         rpainmap_t ip;
98 } rpastat_t;
99
100
101 rpa_compiler_t *rpa_compiler_create()
102 {
103         rpa_compiler_t *co;
104
105         co = r_malloc(sizeof(*co));
106         r_memset(co, 0, sizeof(*co));
107         co->cg = rvm_codegen_create();
108         co->scope = rvm_scope_create();
109         return co;
110 }
111
112
113 void rpa_compiler_destroy(rpa_compiler_t *co)
114 {
115         if (co) {
116                 rvm_codegen_destroy(co->cg);
117                 rvm_scope_destroy(co->scope);
118         }
119         r_free(co);
120 }
121
122 rpastat_t *rpa_stat_create()
123 {
124         rpastat_t *stat = (rpastat_t *) r_zmalloc(sizeof(*stat));
125         stat->records = r_array_create(sizeof(rparecord_t));
126         return stat;
127 }
128
129
130 int rpa_stat_init(rpastat_t *stat, const rchar *input, const rchar *start, const rchar *end)
131 {
132         rulong size;
133
134         if (start > end) {
135
136                 return -1;
137         }
138         if (input < start || input > end) {
139
140                 return -1;
141         }
142         size = end - start;
143         stat->start = start;
144         stat->end = end;
145         stat->input = input;
146         stat->error = 0;
147         stat->cursize = 0;
148         if (stat->instacksize < size) {
149                 stat->instack = r_realloc(stat->instack, (size + 1) * sizeof(rpainput_t));
150                 stat->instacksize = size + 1;
151         }
152         stat->ip.input = input;
153         stat->ip.serial = 0;
154         r_array_setlength(stat->records, 0);
155         return 0;
156 }
157
158
159 void rpa_stat_destroy(rpastat_t *stat)
160 {
161         if (stat->instack)
162                 r_free(stat->instack);
163         r_object_destroy((robject_t*)stat->records);
164         r_free(stat);
165 }
166
167
168 static void rpa_shift(rvmcpu_t *cpu, rvm_asmins_t *ins)
169 {
170         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
171         rlong tp = RVM_CPUREG_GETL(cpu, R_TOP);
172         rpainput_t * ptp = &stat->instack[tp];
173
174         if (ptp->eof)
175                 return;
176         ptp++;
177         tp++;
178         if (tp >= (rlong)stat->ip.serial) {
179                 rint inc = 0;
180                 ptp->input = stat->ip.input;
181                 if (ptp->input < stat->end) {
182                         inc = r_utf8_mbtowc(&ptp->wc, (const ruchar*)stat->ip.input, (const ruchar*)stat->end);
183                         stat->ip.input += inc;
184                         stat->ip.serial += 1;
185                         ptp->eof = 0;
186                 } else {
187                         ptp->wc = (ruint32)-1;
188                         ptp->eof = 1;
189                 }
190         }
191         RVM_CPUREG_SETL(cpu, R_TOP, tp);
192 }
193
194
195 static void rpa_eqshift(rvmcpu_t *cpu, rvm_asmins_t *ins)
196 {
197         if (cpu->status & RVM_STATUS_Z)
198                 rpa_shift(cpu, ins);
199 }
200
201
202 static void rpa_neqshift(rvmcpu_t *cpu, rvm_asmins_t *ins)
203 {
204         if (!(cpu->status & RVM_STATUS_Z))
205                 rpa_shift(cpu, ins);
206 }
207
208
209 static void rpa_matchchr_do(rvmcpu_t *cpu, rvm_asmins_t *ins, rword flags)
210 {
211         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
212         rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
213         rword matched = 0;
214
215         if (flags == RPA_MATCH_OPTIONAL) {
216                 if (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc) {
217                         rpa_shift(cpu, ins);
218                         matched = 1;
219                 }
220                 cpu->status = matched ? 0 : RVM_STATUS_Z;
221                 RVM_CPUREG_SETU(cpu, R0, matched);
222         } else if (flags == RPA_MATCH_MULTIPLE) {
223                 while (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc) {
224                         rpa_shift(cpu, ins);
225                         matched += 1;
226                 }
227                 cpu->status = matched ? 0 : RVM_STATUS_N;
228                 RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
229         } else if (flags == RPA_MATCH_MULTIOPT) {
230                 while (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc) {
231                         rpa_shift(cpu, ins);
232                         matched += 1;
233                 }
234                 cpu->status = matched ? 0 : RVM_STATUS_Z;
235                 RVM_CPUREG_SETU(cpu, R0, matched );
236         } else {
237                 if (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc) {
238                         rpa_shift(cpu, ins);
239                         matched = 1;
240                 }
241                 cpu->status = matched ? 0 : RVM_STATUS_N;
242                 RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
243         }
244
245 }
246
247
248 static void rpa_matchany_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
249 {
250         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
251
252         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof) ? 0 : 1);
253         if (!(cpu->status & RVM_STATUS_N))
254                 rpa_shift(cpu, ins);
255 }
256
257
258 static void rpa_matcheol_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
259 {
260         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
261
262         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && r_strchr("\r\n", stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc)) ? 0 : 1);
263         if (!(cpu->status & RVM_STATUS_N))
264                 rpa_shift(cpu, ins);
265 }
266
267
268 static void rpa_matchchr_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
269 {
270 //      rpastat_t *stat = (rpastat_t *)cpu->userdata1;
271 //      rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
272 //
273 //      RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc) ? 0 : 1);
274 //      if (!(cpu->status & RVM_STATUS_N))
275 //              rpa_shift(cpu, ins);
276
277         rpa_matchchr_do(cpu, ins, RPA_MATCH_NONE);
278 }
279
280
281 static void rpa_matchchr_opt(rvmcpu_t *cpu, rvm_asmins_t *ins)
282 {
283         rpa_matchchr_do(cpu, ins, RPA_MATCH_OPTIONAL);
284 }
285
286
287 static void rpa_matchchr_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
288 {
289         rpa_matchchr_do(cpu, ins, RPA_MATCH_MULTIPLE);
290 }
291
292
293 static void rpa_matchchr_mop(rvmcpu_t *cpu, rvm_asmins_t *ins)
294 {
295         rpa_matchchr_do(cpu, ins, RPA_MATCH_MULTIOPT);
296 }
297
298
299
300 static void rpa_matchrng(rvmcpu_t *cpu, rvm_asmins_t *ins)
301 {
302         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
303         rlong tp = RVM_CPUREG_GETL(cpu, R_TOP);
304         rpair_t op1 = RVM_CPUREG_GETPAIR(cpu, ins->op1);
305
306         RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && stat->instack[tp].wc >= op1.p1 && stat->instack[tp].wc <= op1.p2) ? 1 : 0);
307 }
308
309
310 static void rpa_emitstart(rvmcpu_t *cpu, rvm_asmins_t *ins)
311 {
312         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
313         rparecord_t *rec;
314         rlong index;
315         rword tp = RVM_CPUREG_GETU(cpu, ins->op2);
316         rstr_t name = {RVM_CPUREG_GETSTR(cpu, ins->op1), RVM_CPUREG_GETSIZE(cpu, ins->op1)};
317
318         index = r_array_add(stat->records, NULL);
319         rec = (rparecord_t *)r_array_slot(stat->records, index);
320         rec->rule = name.str;
321         rec->top = tp;
322         rec->type = RPA_RECORD_START;
323 //      r_printf("START: %s(%ld)\n", name.str, (rulong)tp);
324 }
325
326
327 static void rpa_emitend(rvmcpu_t *cpu, rvm_asmins_t *ins)
328 {
329         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
330         rparecord_t *rec;
331         rlong index;
332         rword tp = RVM_CPUREG_GETU(cpu, ins->op2);
333         rword tplen = RVM_CPUREG_GETU(cpu, ins->op3);
334         rstr_t name = {RVM_CPUREG_GETSTR(cpu, ins->op1), RVM_CPUREG_GETSIZE(cpu, ins->op1)};
335
336         index = r_array_add(stat->records, NULL);
337         rec = (rparecord_t *)r_array_slot(stat->records, index);
338         rec->rule = name.str;
339         rec->top = tp;
340         rec->size = tplen;
341         rec->type = RPA_RECORD_START;
342
343         if (tplen) {
344                 rec->type = RPA_RECORD_END | RPA_RECORD_MATCH;
345 //              r_printf("MATCHED: %s(%ld, %ld): %p(%d)\n", name.str, (rulong)tp, (rulong)tplen, name.str, name.size);
346         } else {
347                 rec->type = RPA_RECORD_END;
348 //              r_printf("MATCHED: %s(%ld, %ld)\n", name.str, (rulong)tp, (rulong)tplen);
349         }
350 }
351
352
353 static void rpa_bxlwht(rvmcpu_t *cpu, rvm_asmins_t *ins)
354 {
355         rword wht = RVM_CPUREG_GETU(cpu, ins->op2);
356
357         RVM_CPUREG_SETU(cpu, R_WHT, wht);
358         RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
359         RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
360 }
361
362
363 static rvm_switable_t switable[] = {
364                 {"RPA_MATCHCHR_NAN", rpa_matchchr_nan},
365                 {"RPA_MATCHCHR_OPT", rpa_matchchr_opt},
366                 {"RPA_MATCHCHR_MUL", rpa_matchchr_mul},
367                 {"RPA_MATCHCHR_MOP", rpa_matchchr_mop},
368                 {"RPA_SHIFT", rpa_shift},
369                 {"RPA_EQSHIFT", rpa_eqshift},
370                 {"RPA_NEQSHIFT", rpa_neqshift},
371                 {"RPA_EMITSTART", rpa_emitstart},
372                 {"RPA_EMITEND", rpa_emitend},
373                 {"RPA_MATCHANY_NAN", rpa_matchany_nan},
374                 {"RPA_MATCHEOL_NAN", rpa_matcheol_nan},
375                 {"RPA_BXLWHT", rpa_bxlwht},
376                 {NULL, NULL},
377 };
378
379
380 void codegen_rpa_match(rpa_compiler_t *co)
381 {
382         rvm_codegen_addlabel_s(co->cg, "rpa_match");
383         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BITS(R_TOP,LR)));
384         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, FP, SP, XX, 0));
385         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
386         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
387         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(R_TOP,LR)));
388         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
389         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 2));
390         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, R_TOP, R_TOP, R0, 0));
391         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
392 }
393
394
395 void codegen_rpa_match_mul(rpa_compiler_t *co)
396 {
397         rvm_codegen_addlabel_s(co->cg, "rpa_match_mul");
398         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, DA, XX, 0));
399         rvm_codegen_addlabel_s(co->cg, "rpa_match_mul_again");
400         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R1, XX, XX, 0));           // Ret
401         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BITS(R_TOP,LR)));
402         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, FP, SP, XX, 0));
403         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
404         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
405         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(R_TOP,LR)));
406         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));            // Ret
407         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
408         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 4));
409         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, R_TOP, R_TOP, R0, 0));
410         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, R1, R1, R0, 0));
411         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_match_mul_again", rvm_asm(RVM_B, DA, XX, XX, 0));
412         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, R1, XX, 0));
413         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
414 }
415
416
417 void codegen_rpa_match_char(rpa_compiler_t *co, rword wc, rchar q)
418 {
419         if (q == '?') {
420                 rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_OPT, DA, XX, XX, wc));
421         } else if (q == '+') {
422                 rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_MUL, DA, XX, XX, wc));
423                 rvm_codegen_addins(co->cg, rvm_asm(RVM_BXNEQ, LR, XX, XX, 0));
424         } else if (q == '*') {
425                 rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_MOP, DA, XX, XX, wc));
426         } else {
427                 rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, wc));
428                 rvm_codegen_addins(co->cg, rvm_asm(RVM_BXNEQ, LR, XX, XX, 0));
429         }
430 }
431
432
433 void codegen_rpa_match_mnode(rpa_compiler_t *co)
434 {
435         rvm_codegen_addlabel_s(co->cg, "rpa_match_mnode");
436         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BITS(R_TOP,LR)));
437         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, FP, SP, XX, 0));
438         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
439         rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
440         rvm_codegen_addins(co->cg, rvm_asm(RVM_BLES, DA, XX, XX, 3));
441         rvm_codegen_addins(co->cg, rvm_asm(RVM_TST, R0, R_FLG, DA, RPA_MATCH_MULTIPLE));
442         rvm_codegen_addins(co->cg, rvm_asm(RVM_BNEQ, DA, XX, XX, -4));
443         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R_TOP, XX, 0));
444         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
445         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(R_TOP,LR)));
446         rvm_codegen_addins(co->cg, rvm_asm(RVM_SWP, R1, R_TOP, XX, 0));
447         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
448         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 2));
449         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
450         rvm_codegen_addins(co->cg, rvm_asm(RVM_TST, R_FLG, DA, XX, RPA_MATCH_OPTIONAL));
451         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXNEQ, LR, XX, XX, 0));
452         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDS, R0, R0, DA, -1));
453         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
454 }
455
456
457 void codegen_rpa_mnode_nan(rpa_compiler_t *co)
458 {
459         rvm_codegen_addlabel_s(co->cg, "rpa_mnode_nan");
460         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, R_WHT, XX, XX, 0));
461 }
462
463
464 void codegen_rpa_mnode_opt(rpa_compiler_t *co)
465 {
466         rvm_codegen_addlabel_s(co->cg, "rpa_mnode_opt");
467         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
468         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
469         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
470         rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
471         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXGRE, LR, XX, XX, 0));
472         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, 0));
473         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, R0, XX, 0));
474         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
475 }
476
477
478 void codegen_rpa_mnode_mul(rpa_compiler_t *co)
479 {
480         rvm_codegen_addlabel_s(co->cg, "rpa_mnode_mul");
481         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
482         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
483         rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
484         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 2));
485         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, PC, XX, XX, 0));
486         rvm_codegen_addins(co->cg, rvm_asm(RVM_CLR, R1, XX, XX, 0));
487         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, R0, R0, R1, 0));
488         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
489         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
490         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
491         rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
492         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, -5));
493         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDS, R0, R1, DA, 0));
494         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, PC, XX, XX, 0));
495 }
496
497
498 void codegen_rpa_mnode_mop(rpa_compiler_t *co)
499 {
500         rulong ruleidx;
501         const rchar *rule = "rpa_mnode_mop";
502
503         ruleidx = rvm_codegen_addstring_s(co->cg, NULL, rule);
504
505         rvm_codegen_addlabel_s(co->cg, "rpa_mnode_mop");
506         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, LR, XX, XX, 0));
507         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
508         rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
509         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 4));
510         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, 0));
511         rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, R0, XX, 0));
512         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, PC, XX, XX, 0));
513         rvm_codegen_addins(co->cg, rvm_asm(RVM_CLR, R1, XX, XX, 0));
514         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, R0, R0, R1, 0));
515         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
516         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R_WHT, XX, XX, 0));
517         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
518         rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
519         rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, -5));
520         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDS, R0, R1, DA, 0));
521         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, PC, XX, XX, 0));
522 }
523
524
525 void codegen_rpa_match_aorb(rpa_compiler_t *co)
526 {
527         rulong ruleidx;
528         const rchar *rule = "rpa_match_aorb";
529         const rchar *ruleend = "rpa_match_aorb_end";
530
531         ruleidx = rvm_codegen_addstring_s(co->cg, NULL, rule);
532         rvm_codegen_addlabel_s(co->cg, rule);
533
534         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
535         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
536
537         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'a'));
538         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
539
540         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_MOP, DA, XX, XX, 'b'));
541         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
542
543         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
544         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
545         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
546         rvm_codegen_addlabel_s(co->cg, ruleend);
547         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_WHT)|BIT(LR)));
548         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
549         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITEND, DA, R1, R0, 0));
550         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
551 }
552
553
554 void codegen_rpa_match_xyz(rpa_compiler_t *co)
555 {
556         rulong ruleidx;
557         const rchar *rule = "rpa_match_xyz";
558         const rchar *ruleend = "rpa_match_xyz_end";
559
560         ruleidx = rvm_codegen_addstring_s(co->cg, NULL, rule);
561         rvm_codegen_addlabel_s(co->cg, rule);
562
563         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
564         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
565
566         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_squared", rvm_asm(RPA_BXLWHT, R_MNODE_MOP, DA, XX, 0));
567         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
568
569         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'x'));
570         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
571
572         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_MOP, DA, XX, XX, 'y'));
573         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
574
575         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'z'));
576         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
577
578         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_WHT)|BIT(LR)));
579         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
580         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITEND, DA, R1, R0, 0));
581         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
582         rvm_codegen_addlabel_s(co->cg, ruleend);
583         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
584         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
585         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
586 }
587
588
589 void codegen_rpa_match_abc(rpa_compiler_t *co)
590 {
591         rulong ruleidx;
592         const rchar *rule = "rpa_match_abc";
593         const rchar *ruleend = "rpa_match_abc_end";
594
595         ruleidx = rvm_codegen_addstring_s(co->cg, NULL, rule);
596         rvm_codegen_addlabel_s(co->cg, rule);
597
598         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
599         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
600
601         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'a'));
602         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
603
604         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_MOP, DA, XX, XX, 'b'));
605         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
606
607         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'c'));
608         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
609
610
611         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_WHT)|BIT(LR)));
612         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
613         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITEND, DA, R1, R0, 0));
614         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
615         rvm_codegen_addlabel_s(co->cg, ruleend);
616         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
617         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
618         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
619 }
620
621
622 void codegen_rpa_match_xyzorabc(rpa_compiler_t *co)
623 {
624         rulong ruleidx;
625         const rchar *rule = "rpa_match_xyzorabc";
626         const rchar *ruleend = "rpa_match_xyzorabc_end";
627
628         ruleidx = rvm_codegen_addstring_s(co->cg, NULL, rule);
629         rvm_codegen_addlabel_s(co->cg, rule);
630         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
631         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
632
633
634         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_xyz", rvm_asm(RPA_BXLWHT, R_MNODE_MOP, DA, XX, 0));
635         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
636
637         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_abc", rvm_asm(RPA_BXLWHT, R_MNODE_MOP, DA, XX, 0));
638         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
639
640         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
641         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
642         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
643         rvm_codegen_addlabel_s(co->cg, ruleend);
644         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_WHT)|BIT(LR)));
645         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
646         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITEND, DA, R1, R0, 0));
647         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
648 }
649
650
651
652 void codegen_rpa_match_squared(rpa_compiler_t *co)
653 {
654         rulong ruleidx;
655         const rchar *rule = "rpa_match_squared";
656         const rchar *ruleend = "rpa_match_squared_end";
657
658         ruleidx = rvm_codegen_addstring_s(co->cg, NULL, rule);
659         rvm_codegen_addlabel_s(co->cg, rule);
660         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITSTART, DA, R_TOP, XX, 0));
661         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
662
663         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, '['));
664         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
665
666         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_xyzorabc", rvm_asm(RPA_BXLWHT, R_MNODE_MOP, DA, XX, 0));
667         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
668
669         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_aorb", rvm_asm(RPA_BXLWHT, R_MNODE_MOP, DA, XX, 0));
670         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
671
672         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, ']'));
673         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
674
675         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_matcheol_char", rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
676         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_mnode_mop", rvm_asm(RVM_BL, DA, XX, XX, 0));
677         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, ruleend, rvm_asm(RVM_BLES, DA, XX, XX, 0));
678
679         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R1)|BIT(R_WHT)|BIT(LR)));
680         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
681         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_STRING, ruleidx, rvm_asm(RPA_EMITEND, DA, R1, R0, 0));
682         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
683         rvm_codegen_addlabel_s(co->cg, ruleend);
684         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BIT(R_TOP)|BIT(R_WHT)|BIT(LR)));
685         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
686         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
687 }
688
689
690
691
692 /*
693  * R0 Char
694  * R1 Flags
695  * Return:
696  * R0 = -1 No match
697  * R0 = 0 Didn't match, but it was optional
698  * R0 > 0 matched R0 TPs
699  */
700
701 void rpa_match_char(rpa_compiler_t *co)
702 {
703         rvm_codegen_addlabel_s(co->cg, "rpa_match_char");
704         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BITS(R_TOP,LR)));
705         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, FP, SP, XX, 0));
706         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, R_ARG, XX, XX, 0));
707         rvm_codegen_addins(co->cg, rvm_asm(RVM_BNEQ, DA, XX, XX, 3));
708         rvm_codegen_addins(co->cg, rvm_asm(RVM_TST, R0, R_FLG, DA, RPA_MATCH_MULTIPLE));
709         rvm_codegen_addins(co->cg, rvm_asm(RVM_BNEQ, DA, XX, XX, -3));
710         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R_TOP, XX, 0));
711         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
712         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(R_TOP,LR)));
713         rvm_codegen_addins(co->cg, rvm_asm(RVM_SWP, R1, R_TOP, XX, 0));
714         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUBS, R0, R_TOP, R1, 0));
715         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 2));
716         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
717         rvm_codegen_addins(co->cg, rvm_asm(RVM_TST, R0, R_FLG, DA, RPA_MATCH_OPTIONAL));
718         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXNEQ, LR, XX, XX, 0));
719         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
720         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
721 }
722
723
724 void rpa_matchonly_char(rpa_compiler_t *co)
725 {
726         rvm_codegen_addlabel_s(co->cg, "rpa_matchonly_char");
727         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
728         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, R_ARG, XX, XX, 0));
729         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXLES, LR, XX, XX, 0));
730         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, 1));
731         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
732 }
733
734
735 void rpa_matchany_char(rpa_compiler_t *co)
736 {
737         rvm_codegen_addlabel_s(co->cg, "rpa_matchany_char");
738         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
739         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHANY_NAN, R_ARG, XX, XX, 0));
740         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXLES, LR, XX, XX, 0));
741         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, 1));
742         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
743 }
744
745
746 void rpa_matcheol_char(rpa_compiler_t *co)
747 {
748         rvm_codegen_addlabel_s(co->cg, "rpa_matcheol_char");
749         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, -1));
750         rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHEOL_NAN, R_ARG, XX, XX, 0));
751         rvm_codegen_addins(co->cg, rvm_asm(RVM_BXLES, LR, XX, XX, 0));
752         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, 1));
753         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
754 }
755
756
757 void codegen_unmap_file(rstr_t *buf)
758 {
759         if (buf) {
760                 munmap(buf->str, buf->size);
761                 r_free(buf);
762         }
763 }
764
765
766 rstr_t *codegen_map_file(const char *filename)
767 {
768         struct stat st;
769         rstr_t *str;
770         char *buffer;
771
772
773         int fd = open(filename, O_RDONLY);
774         if (fd < 0) {
775                 return (void*)0;
776         }
777         if (fstat(fd, &st) < 0) {
778                 close(fd);
779                 return (void*)0;
780         }
781         buffer = (char*)mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
782         if (buffer == (void*)-1) {
783                 close(fd);
784                 return (void*)0;
785         }
786         str = (rstr_t *)r_malloc(sizeof(*str));
787         if (!str)
788                 goto error;
789         r_memset(str, 0, sizeof(*str));
790         str->str = buffer;
791         str->size = st.st_size;
792         close(fd);
793         return str;
794
795 error:
796         munmap(buffer, st.st_size);
797         close(fd);
798         return str;
799 }
800
801
802 int main(int argc, char *argv[])
803 {
804         rstr_t *script = NULL, *unmapscript = NULL;
805         rvmcpu_t *cpu;
806         rvm_codelabel_t *err;
807         rpa_compiler_t *co;
808         rpastat_t *stat;
809         rint i;
810
811         co = rpa_compiler_create();
812         cpu = rvm_cpu_create_default();
813         cpu->userdata1 = stat = rpa_stat_create();
814         regextable = rvm_cpu_addswitable(cpu, switable);
815
816         for (i = 1; i < argc; i++) {
817                 if (r_strcmp(argv[i], "-L") == 0) {
818                 } else if (r_strcmp(argv[i], "-d") == 0) {
819                         debuginfo = 1;
820                 } else if (r_strcmp(argv[i], "-c") == 0) {
821                         compileonly = 1;
822                 } else if (r_strcmp(argv[i], "-p") == 0) {
823                         parseinfo = 1;
824                 }
825         }
826
827         for (i = 1; i < argc; i++) {
828                 if (r_strcmp(argv[i], "-e") == 0) {
829                         if (++i < argc) {
830                                 rstr_t bnfexpr = { argv[i], r_strlen(argv[i]) };
831                                 rpa_stat_init((rpastat_t *)cpu->userdata1, bnfexpr.str, bnfexpr.str, bnfexpr.str + bnfexpr.size);
832                         }
833                 }
834         }
835
836         for (i = 1; i < argc; i++) {
837                 if (r_strcmp(argv[i], "-f") == 0) {
838                         if (++i < argc) {
839                                 script = codegen_map_file(argv[i]);
840                                 if (script) {
841                                         rpa_stat_init((rpastat_t *)cpu->userdata1, script->str, script->str, script->str + script->size);
842                                         unmapscript = script;
843                                 }
844                         }
845                         goto exec;
846                 }
847         }
848
849
850 exec:
851
852         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));
853         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, FP, DA, XX, 0));
854         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, SP, DA, XX, co->fpoff));
855
856         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_mnode_nan", rvm_asm(RVM_MOV, R_MNODE_NAN, DA, XX, 0));
857         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_mnode_mul", rvm_asm(RVM_MOV, R_MNODE_MUL, DA, XX, 0));
858         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_mnode_opt", rvm_asm(RVM_MOV, R_MNODE_OPT, DA, XX, 0));
859         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_mnode_mop", rvm_asm(RVM_MOV, R_MNODE_MOP, DA, XX, 0));
860
861         rvm_codegen_addins(co->cg, rvm_asm(RPA_SHIFT, XX, XX, XX, 0));
862
863
864 //      rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_FLG, DA, XX, RPA_MATCH_NONE));
865 //      rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_squared", rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
866 //      rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_mnode_mul", rvm_asm(RVM_BL, DA, XX, XX, 0));
867
868         rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_squared", rvm_asm(RPA_BXLWHT, R_MNODE_MUL, DA, XX, 0));
869
870
871 //      rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_match_xyz_p", rvm_asm(RVM_MOV, R_WHT, DA, XX, 0));
872 //      rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_BRANCH, "rpa_match_mnode", rvm_asm(RVM_BL, DA, XX, XX, 0));
873
874         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0xabc));
875         rvm_codegen_addins(co->cg, rvm_asm(RVM_EXT, XX, XX, XX, 0));
876
877         rpa_match_char(co);
878         rpa_matchonly_char(co);
879         codegen_rpa_match_abc(co);
880         codegen_rpa_match_xyz(co);
881         codegen_rpa_match_xyzorabc(co);
882         codegen_rpa_match_aorb(co);
883         codegen_rpa_match_squared(co);
884         codegen_rpa_match_mnode(co);
885         codegen_rpa_match(co);
886         codegen_rpa_match_mul(co);
887         rpa_matcheol_char(co);
888         rpa_matchany_char(co);
889
890         codegen_rpa_mnode_nan(co);
891         codegen_rpa_mnode_opt(co);
892         codegen_rpa_mnode_mul(co);
893         codegen_rpa_mnode_mop(co);
894
895
896         if (rvm_codegen_relocate(co->cg, &err) < 0) {
897                 r_printf("Unresolved symbol: %s\n", err->name->str);
898                 goto end;
899         }
900
901         if (debuginfo) {
902                 fprintf(stdout, "\nGenerated Code:\n");
903                 rvm_asm_dump(rvm_codegen_getcode(co->cg, 0), rvm_codegen_getcodesize(co->cg));
904                 if (rvm_codegen_getcodesize(co->cg)) {
905                         if (!compileonly) {
906                                 fprintf(stdout, "\nExecution:\n");
907                                 rvm_cpu_exec_debug(cpu, rvm_codegen_getcode(co->cg, 0), 0);
908                         }
909                 }
910         } else {
911                 if (!compileonly)
912                         rvm_cpu_exec(cpu, rvm_codegen_getcode(co->cg, 0), 0);
913         }
914
915         r_printf("Matched: %d\n", RVM_CPUREG_GETU(cpu, R0));
916 end:
917
918         for (i = 0; 0 && i < r_array_length(stat->records); i++) {
919                 rparecord_t *rec = (rparecord_t *)r_array_slot(stat->records, i);
920                 if (rec->type & RPA_RECORD_MATCH) {
921                         r_printf("%d: rule: %s(%d, %d)\n", i, rec->rule, (rint)rec->top, (rint)rec->size);
922                 }
923         }
924
925         rpa_stat_destroy((rpastat_t *)cpu->userdata1);
926         rvm_cpu_destroy(cpu);
927         rpa_compiler_destroy(co);
928         if (unmapscript)
929                 codegen_unmap_file(unmapscript);
930
931
932         if (1||debuginfo) {
933                 r_printf("Max alloc mem: %ld\n", r_debug_get_maxmem());
934                 r_printf("Leaked mem: %ld\n", r_debug_get_allocmem());
935         }
936         return 0;
937 }