RPA Toolkit
work on RVM based parser - RPA2
[rpatk.git] / rpa2 / rpavm.c
1 #include "rpavm.h"
2 #include "rpastat.h"
3 #include "rutf.h"
4
5
6 static void rpavm_swi_shift(rvmcpu_t *cpu, rvm_asmins_t *ins)
7 {
8         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
9         rlong tp = RVM_CPUREG_GETL(cpu, R_TOP);
10         rpainput_t * ptp = &stat->instack[tp];
11
12         if (ptp->eof)
13                 return;
14         ptp++;
15         tp++;
16         if (tp >= (rlong)stat->ip.serial) {
17                 rint inc = 0;
18                 ptp->input = stat->ip.input;
19                 if (ptp->input < stat->end) {
20                         inc = r_utf8_mbtowc(&ptp->wc, (const ruchar*)stat->ip.input, (const ruchar*)stat->end);
21                         stat->ip.input += inc;
22                         stat->ip.serial += 1;
23                         ptp->eof = 0;
24                 } else {
25                         ptp->wc = (ruint32)-1;
26                         ptp->eof = 1;
27                 }
28         }
29         RVM_CPUREG_SETL(cpu, R_TOP, tp);
30 }
31
32
33 static void rpavm_matchchr_do(rvmcpu_t *cpu, rvm_asmins_t *ins, rword flags)
34 {
35         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
36         rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
37         rword matched = 0;
38
39         if (flags == RPA_MATCH_OPTIONAL) {
40                 if (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc) {
41                         rpavm_swi_shift(cpu, ins);
42                         matched = 1;
43                 }
44                 cpu->status = matched ? 0 : RVM_STATUS_Z;
45                 RVM_CPUREG_SETU(cpu, R0, matched);
46         } else if (flags == RPA_MATCH_MULTIPLE) {
47                 while (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc) {
48                         rpavm_swi_shift(cpu, ins);
49                         matched += 1;
50                 }
51                 cpu->status = matched ? 0 : RVM_STATUS_N;
52                 RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
53         } else if (flags == RPA_MATCH_MULTIOPT) {
54                 while (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc) {
55                         rpavm_swi_shift(cpu, ins);
56                         matched += 1;
57                 }
58                 cpu->status = matched ? 0 : RVM_STATUS_Z;
59                 RVM_CPUREG_SETU(cpu, R0, matched );
60         } else {
61                 if (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc) {
62                         rpavm_swi_shift(cpu, ins);
63                         matched = 1;
64                 }
65                 cpu->status = matched ? 0 : RVM_STATUS_N;
66                 RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
67         }
68 }
69
70
71 static void rpavm_matchspchr_do(rvmcpu_t *cpu, rvm_asmins_t *ins, rword flags)
72 {
73         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
74         rword wc = RVM_CPUREG_GETU(cpu, ins->op1);
75         rword matched = 0;
76
77         switch (wc) {
78                 case 't':
79                         wc = '\t';
80                         break;
81                 case 'r':
82                         wc = '\r';
83                         break;
84                 case 'n':
85                         wc = '\n';
86                         break;
87                 case '.':
88                         wc = (rword)-1;
89                         break;
90                 default:
91                         break;
92         };
93
94         if (flags == RPA_MATCH_OPTIONAL) {
95                 if (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && (wc == (rword)-1 || stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc)) {
96                         rpavm_swi_shift(cpu, ins);
97                         matched = 1;
98                 }
99                 cpu->status = matched ? 0 : RVM_STATUS_Z;
100                 RVM_CPUREG_SETU(cpu, R0, matched);
101         } else if (flags == RPA_MATCH_MULTIPLE) {
102                 while (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && (wc == (rword)-1 || stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc)) {
103                         rpavm_swi_shift(cpu, ins);
104                         matched += 1;
105                 }
106                 cpu->status = matched ? 0 : RVM_STATUS_N;
107                 RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
108         } else if (flags == RPA_MATCH_MULTIOPT) {
109                 while (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && (wc == (rword)-1 || stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc)) {
110                         rpavm_swi_shift(cpu, ins);
111                         matched += 1;
112                 }
113                 cpu->status = matched ? 0 : RVM_STATUS_Z;
114                 RVM_CPUREG_SETU(cpu, R0, matched );
115         } else {
116                 if (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof && (wc == (rword)-1 || stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].wc == wc)) {
117                         rpavm_swi_shift(cpu, ins);
118                         matched = 1;
119                 }
120                 cpu->status = matched ? 0 : RVM_STATUS_N;
121                 RVM_CPUREG_SETU(cpu, R0, matched ? matched : (rword)-1);
122         }
123 }
124
125
126 static void rpavm_swi_matchchr_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
127 {
128         rpavm_matchchr_do(cpu, ins, RPA_MATCH_NONE);
129 }
130
131
132 static void rpavm_swi_matchchr_opt(rvmcpu_t *cpu, rvm_asmins_t *ins)
133 {
134         rpavm_matchchr_do(cpu, ins, RPA_MATCH_OPTIONAL);
135 }
136
137
138 static void rpavm_swi_matchchr_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
139 {
140         rpavm_matchchr_do(cpu, ins, RPA_MATCH_MULTIPLE);
141 }
142
143
144 static void rpavm_swi_matchchr_mop(rvmcpu_t *cpu, rvm_asmins_t *ins)
145 {
146         rpavm_matchchr_do(cpu, ins, RPA_MATCH_MULTIOPT);
147 }
148
149
150
151
152 static void rpavm_swi_matchspchr_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
153 {
154         rpavm_matchspchr_do(cpu, ins, RPA_MATCH_NONE);
155 }
156
157
158 static void rpavm_swi_matchspchr_opt(rvmcpu_t *cpu, rvm_asmins_t *ins)
159 {
160         rpavm_matchspchr_do(cpu, ins, RPA_MATCH_OPTIONAL);
161 }
162
163
164 static void rpavm_swi_matchspchr_mul(rvmcpu_t *cpu, rvm_asmins_t *ins)
165 {
166         rpavm_matchspchr_do(cpu, ins, RPA_MATCH_MULTIPLE);
167 }
168
169
170 static void rpavm_swi_matchspchr_mop(rvmcpu_t *cpu, rvm_asmins_t *ins)
171 {
172         rpavm_matchspchr_do(cpu, ins, RPA_MATCH_MULTIOPT);
173 }
174
175
176
177
178 static void rpavm_swi_matchany_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
179 {
180         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
181
182         RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, (!stat->instack[RVM_CPUREG_GETL(cpu, R_TOP)].eof) ? 0 : 1);
183         if (!(cpu->status & RVM_STATUS_N))
184                 rpavm_swi_shift(cpu, ins);
185 }
186
187
188 static void rpavm_swi_matcheol_nan(rvmcpu_t *cpu, rvm_asmins_t *ins)
189 {
190         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
191
192         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);
193         if (!(cpu->status & RVM_STATUS_N))
194                 rpavm_swi_shift(cpu, ins);
195 }
196
197
198 static void rpavm_swi_emitstart(rvmcpu_t *cpu, rvm_asmins_t *ins)
199 {
200         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
201         rparecord_t *rec;
202         rlong index;
203         rword tp = RVM_CPUREG_GETU(cpu, ins->op2);
204         rstr_t name = {RVM_CPUREG_GETSTR(cpu, ins->op1), RVM_CPUREG_GETSIZE(cpu, ins->op1)};
205
206         index = r_array_add(stat->records, NULL);
207         rec = (rparecord_t *)r_array_slot(stat->records, index);
208         rec->rule = name.str;
209         rec->top = tp;
210         rec->type = RPA_RECORD_START;
211 //      r_printf("START: %s(%ld)\n", name.str, (rulong)tp);
212 }
213
214
215 static void rpavm_swi_emitend(rvmcpu_t *cpu, rvm_asmins_t *ins)
216 {
217         rpastat_t *stat = (rpastat_t *)cpu->userdata1;
218         rparecord_t *rec;
219         rlong index;
220         rword tp = RVM_CPUREG_GETU(cpu, ins->op2);
221         rword tplen = RVM_CPUREG_GETU(cpu, ins->op3);
222         rstr_t name = {RVM_CPUREG_GETSTR(cpu, ins->op1), RVM_CPUREG_GETSIZE(cpu, ins->op1)};
223
224         index = r_array_add(stat->records, NULL);
225         rec = (rparecord_t *)r_array_slot(stat->records, index);
226         rec->rule = name.str;
227         rec->top = tp;
228         rec->size = tplen;
229         rec->type = RPA_RECORD_START;
230
231         if (tplen) {
232                 rec->type = RPA_RECORD_END | RPA_RECORD_MATCH;
233 //              r_printf("MATCHED: %s(%ld, %ld): %p(%d)\n", name.str, (rulong)tp, (rulong)tplen, name.str, name.size);
234         } else {
235                 rec->type = RPA_RECORD_END;
236 //              r_printf("MATCHED: %s(%ld, %ld)\n", name.str, (rulong)tp, (rulong)tplen);
237         }
238 }
239
240
241 static void rpavm_swi_bxlwht(rvmcpu_t *cpu, rvm_asmins_t *ins)
242 {
243         rword wht = RVM_CPUREG_GETU(cpu, ins->op2);
244
245         RVM_CPUREG_SETU(cpu, R_WHT, wht);
246         RVM_CPUREG_SETIP(cpu, LR, RVM_CPUREG_GETIP(cpu, PC));
247         RVM_CPUREG_SETIP(cpu, PC, RVM_CPUREG_GETIP(cpu, ins->op1));
248 }
249
250
251 static rvm_switable_t rpavm_swi_table[] = {
252                 {"RPA_MATCHCHR_NAN", rpavm_swi_matchchr_nan},
253                 {"RPA_MATCHCHR_OPT", rpavm_swi_matchchr_opt},
254                 {"RPA_MATCHCHR_MUL", rpavm_swi_matchchr_mul},
255                 {"RPA_MATCHCHR_MOP", rpavm_swi_matchchr_mop},
256                 {"RPA_MATCHSPCHR_NAN", rpavm_swi_matchspchr_nan},
257                 {"RPA_MATCHSPCHR_OPT", rpavm_swi_matchspchr_opt},
258                 {"RPA_MATCHSPCHR_MUL", rpavm_swi_matchspchr_mul},
259                 {"RPA_MATCHSPCHR_MOP", rpavm_swi_matchspchr_mop},
260                 {"RPA_SHIFT", rpavm_swi_shift},
261                 {"RPA_EMITSTART", rpavm_swi_emitstart},
262                 {"RPA_EMITEND", rpavm_swi_emitend},
263                 {"RPA_MATCHANY_NAN", rpavm_swi_matchany_nan},
264                 {"RPA_MATCHEOL_NAN", rpavm_swi_matcheol_nan},
265                 {"RPA_BXLWHT", rpavm_swi_bxlwht},
266                 {NULL, NULL},
267 };
268
269
270 rvmcpu_t *rpavm_cpu_create(rulong stacksize)
271 {
272         rvmcpu_t *cpu = rvm_cpu_create(stacksize);
273         rint tableid = rvm_cpu_addswitable(cpu, rpavm_swi_table);
274
275         if (tableid != RPAVM_SWI_TABLEID) {
276                 rpavm_cpu_destroy(cpu);
277                 return NULL;
278         }
279         return cpu;
280 }
281
282
283 void rpavm_cpu_destroy(rvmcpu_t * cpu)
284 {
285         rvm_cpu_destroy(cpu);
286 }
287
288