RPA Toolkit
Work on the RJS compiler
[rpatk.git] / rpa2 / rparecord.c
1 #include "rmem.h"
2 #include "rstring.h"
3 #include "rpaparser.h"
4 #include "rparecord.h"
5
6
7 rparecord_t *rpa_record_get(rarray_t *records, rlong rec)
8 {
9         rparecord_t *prec;
10
11         if (!records)
12                 return NULL;
13         if (rec < 0 || rec >= r_array_length(records))
14                 return NULL;
15         prec = (rparecord_t *)r_array_slot(records, rec);
16         return prec;
17
18 }
19
20
21 rlong rpa_recordtree_get(rarray_t *records, rlong rec, rulong type)
22 {
23         rlong i, s = 0;
24         ruint startrec = (type & RPA_RECORD_START) ? 1 : 0;
25         rparecord_t *prec;
26
27         if (rec < 0 || rec >= r_array_length(records))
28                 return -1;
29         prec = (rparecord_t *)r_array_slot(records, rec);
30         if ((prec->type & RPA_RECORD_START)) {
31                 if (startrec)
32                         return rec;
33                 for (s = 0, i = rec; i < r_array_length(records); i++) {
34                         prec = (rparecord_t *)r_array_slot(records, i);
35                         if (prec->type & RPA_RECORD_START)
36                                 ++s;
37                         if (prec->type & RPA_RECORD_END)
38                                 --s;
39                         if (s == 0)
40                                 return i;
41                 }
42         }
43         prec = (rparecord_t *)r_array_slot(records, rec);
44         if ((prec->type & RPA_RECORD_END)) {
45                 if (!startrec)
46                         return rec;
47                 for (s = 0, i = rec; i >= 0; i--) {
48                         prec = (rparecord_t *)r_array_slot(records, i);
49                         if (prec->type & RPA_RECORD_START)
50                                 ++s;
51                         if (prec->type & RPA_RECORD_END)
52                                 --s;
53                         if (s == 0)
54                                 return i;
55                 }
56         }
57
58         return -1;
59 }
60
61
62 rlong rpa_recordtree_firstchild(rarray_t *records, rlong rec, rulong type)
63 {
64         rparecord_t *prec;
65
66         if (rec < 0 || rec >= r_array_length(records))
67                 return -1;
68         prec = (rparecord_t *)r_array_slot(records, rec);
69         if (prec->type & RPA_RECORD_END) {
70                 if ((rec = rpa_recordtree_get(records, rec, RPA_RECORD_START)) < 0)
71                         return -1;
72         }
73         if (++rec >= r_array_length(records))
74                 return -1;
75         prec = (rparecord_t *)r_array_slot(records, rec);
76         if (prec->type & RPA_RECORD_START)
77                 return rpa_recordtree_get(records, rec, type);
78         return -1;
79 }
80
81
82 rlong rpa_recordtree_lastchild(rarray_t *records, rlong rec, rulong type)
83 {
84         rparecord_t *prec;
85
86         if (rec < 0 || rec >= r_array_length(records))
87                 return -1;
88         prec = (rparecord_t *)r_array_slot(records, rec);
89         if (prec->type & RPA_RECORD_START) {
90                 if ((rec = rpa_recordtree_get(records, rec, RPA_RECORD_END)) < 0)
91                         return -1;
92         }
93         if (--rec < 0)
94                 return -1;
95         prec = (rparecord_t *)r_array_slot(records, rec);
96         if (prec->type & RPA_RECORD_END)
97                 return rpa_recordtree_get(records, rec, type);
98         return -1;
99 }
100
101
102 rlong rpa_recordtree_next(rarray_t *records, rlong rec, rulong type)
103 {
104         rparecord_t *prec;
105
106         if (rec < 0 || rec >= r_array_length(records))
107                 return -1;
108         prec = (rparecord_t *)r_array_slot(records, rec);
109         if (prec->type & RPA_RECORD_START) {
110                 if ((rec = rpa_recordtree_get(records, rec, RPA_RECORD_END)) < 0)
111                         return -1;
112         }
113         if (++rec >= r_array_length(records))
114                 return -1;
115         prec = (rparecord_t *)r_array_slot(records, rec);
116         if (prec->type & RPA_RECORD_START)
117                 return rpa_recordtree_get(records, rec, type);
118         return -1;
119 }
120
121
122 rlong rpa_recordtree_prev(rarray_t *records, rlong rec, rulong type)
123 {
124         rparecord_t *prec;
125
126         if (rec < 0 || rec >= r_array_length(records))
127                 return -1;
128         prec = (rparecord_t *)r_array_slot(records, rec);
129         if (prec->type & RPA_RECORD_END) {
130                 if ((rec = rpa_recordtree_get(records, rec, RPA_RECORD_START)) < 0)
131                         return -1;
132         }
133         if (--rec < 0)
134                 return -1;
135         prec = (rparecord_t *)r_array_slot(records, rec);
136         if (prec->type & RPA_RECORD_END)
137                 return rpa_recordtree_get(records, rec, type);
138         return -1;
139 }
140
141
142 rlong rpa_recordtree_parent(rarray_t *records, rlong rec, rulong type)
143 {
144         rlong last = -1, parent = -1;
145
146         if (rec < 0 || rec >= r_array_length(records))
147                 return -1;
148         for ( ;rec >= 0; rec = rpa_recordtree_next(records, last, RPA_RECORD_END)) {
149                 last = rpa_recordtree_get(records, rec, RPA_RECORD_END);
150         }
151         parent = last + 1;
152         if (parent >= r_array_length(records))
153                 return -1;
154         return rpa_recordtree_get(records, parent, type);
155 }
156
157
158 rlong rpa_recordtree_size(rarray_t *records, rlong rec)
159 {
160         rlong first = rpa_recordtree_get(records, rec, RPA_RECORD_START);
161         rlong last = rpa_recordtree_get(records, rec, RPA_RECORD_END);
162         if (first < 0 || last < 0)
163                 return -1;
164         return (last - first + 1);
165 }
166
167
168 rlong rpa_recordtree_rotatedown(rarray_t *records, rlong parent)
169 {
170         rlong nlastchild;
171         rlong nallrecs = r_array_length(records);
172         rlong firstchild = rpa_recordtree_firstchild(records, parent, RPA_RECORD_START);
173         rlong lastchild = rpa_recordtree_lastchild(records, parent, RPA_RECORD_START);
174         rlong copysiz;
175
176         if (firstchild < 0 || lastchild == firstchild)
177                 return -1;
178         /*
179          * Copy the last child at the end
180          */
181         nlastchild = rpa_recordtree_size(records, lastchild);
182         r_array_move(records, nallrecs, lastchild, nlastchild);
183
184         /*
185          * Push down all children, but the last one (overwriting the last one)
186          */
187         copysiz = lastchild - firstchild;
188         r_array_move(records, firstchild + nlastchild, firstchild, copysiz);
189
190         /*
191          * Copy the last child to become the first one
192          */
193         r_array_move(records, firstchild, nallrecs, nlastchild);
194
195         /*
196          * Restore the original size
197          */
198         r_array_setlength(records, nallrecs);
199         return 0;
200 }
201
202
203 rlong rpa_recordtree_rotateup(rarray_t *records, rlong parent)
204 {
205         /*
206          * Not implemented
207          */
208         return -1;
209 }
210
211
212 rlong rpa_recordtree_copy(rarray_t *dst, rarray_t *src, rlong rec)
213 {
214         rparecord_t *prec;
215         rlong size, i;
216         rec = rpa_recordtree_get(src, rec, RPA_RECORD_START);
217         size = rpa_recordtree_size(src, rec);
218
219         for (i = 0; i < size; i++) {
220                 prec = rpa_record_get(src, i);
221                 r_array_add(dst, prec);
222         }
223         return size;
224 }
225
226
227 rlong rpa_recordtree_walk(rarray_t *records, rlong rec, rlong level, rpa_recordtree_callback callback, rpointer userdata)
228 {
229         rlong child;
230
231         if (level > 128)
232                 return -1;
233         rec = rpa_recordtree_get(records, rec, RPA_RECORD_START);
234         if (callback && callback(records, rec, userdata) < 0)
235                 return -1;
236         for (child = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); child >= 0; child = rpa_recordtree_next(records, child, RPA_RECORD_START)) {
237                 if (rpa_recordtree_walk(records, child, level + 1, callback, userdata) < 0)
238                         return -1;
239         }
240         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
241         if (callback && callback(records, rec, userdata) < 0)
242                 return -1;
243         return 0;
244 }
245
246
247 static void rpa_recordptr_setusertype(rparecord_t *prec, ruint32 usertype, rvalset_t op)
248 {
249         switch (op) {
250         case RVALSET_OR:
251                 prec->usertype |= usertype;
252                 break;
253         case RVALSET_XOR:
254                 prec->usertype ^= usertype;
255                 break;
256         case RVALSET_AND:
257                 prec->usertype &= usertype;
258                 break;
259         default:
260                 prec->usertype = usertype;
261         }
262 }
263
264
265 rlong rpa_record_getruleuid(rarray_t *records, rlong rec)
266 {
267         rparecord_t *prec;
268
269         if (rec < 0)
270                 return -1;
271         rec = rpa_recordtree_get(records, rec, RPA_RECORD_START);
272         if (rec >= r_array_length(records))
273                 return -1;
274         prec = (rparecord_t *)r_array_slot(records, rec);
275         return prec->ruleuid;
276 }
277
278
279 void rpa_record_setusertype(rarray_t *records, rlong rec, ruint32 usertype, rvalset_t op)
280 {
281         rparecord_t *prec;
282
283         if (rec < 0)
284                 return;
285         rec = rpa_recordtree_get(records, rec, RPA_RECORD_START);
286         if (rec >= r_array_length(records))
287                 return;
288         prec = (rparecord_t *)r_array_slot(records, rec);
289         rpa_recordptr_setusertype(prec, usertype, op);
290         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
291         if (rec >= r_array_length(records))
292                 return;
293         prec = (rparecord_t *)r_array_slot(records, rec);
294         rpa_recordptr_setusertype(prec, usertype, op);
295 }
296
297
298 rlong rpa_record_getusertype(rarray_t *records, rlong rec)
299 {
300         rparecord_t *prec;
301
302         if (rec < 0)
303                 return -1;
304         rec = rpa_recordtree_get(records, rec, RPA_RECORD_START);
305         if (rec >= r_array_length(records))
306                 return -1;
307         prec = (rparecord_t *)r_array_slot(records, rec);
308         return prec->usertype;
309 }
310
311
312 rint rpa_record_optchar(rparecord_t *prec, rint defc)
313 {
314         rint optc = defc;
315
316         if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_OPTIONAL)
317                 optc = '?';
318         else if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_MULTIPLE)
319                 optc = '+';
320         else if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_MULTIOPT)
321                 optc = '*';
322         else
323                 optc = defc;
324         return optc;
325 }
326
327
328 rint rpa_record_loopchar(rparecord_t *prec, rint defc)
329 {
330         rint loopc = defc;
331
332         if ((prec->usertype & RPA_LOOP_PATH) && (prec->usertype & RPA_NONLOOP_PATH)) {
333                 /*
334                  * This is an error, should never happen
335                  */
336                 loopc = 'R';
337         } else if ((prec->usertype & RPA_LOOP_PATH)) {
338                 loopc = 'L';
339         } else if ((prec->usertype & RPA_NONLOOP_PATH)) {
340                 loopc = 'N';
341         } else {
342                 loopc = defc;
343         }
344         return loopc;
345 }
346
347
348 void rpa_record_dump(rarray_t *records, rlong rec)
349 {
350         rparecord_t *prec;
351         rlong start, end, first, last, next, prev, parent;
352         rchar buf[240];
353         rint bufsize = sizeof(buf) - 1;
354         rint n = 0, size;
355         rchar optc = ' ';
356
357         if (rec < 0 || rec >= r_array_length(records))
358                 return;
359         prec = (rparecord_t *)r_array_slot(records, rec);
360         if (prec->type & RPA_RECORD_END) {
361                 if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_OPTIONAL)
362                         optc = '?';
363                 else if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_MULTIPLE)
364                         optc = '+';
365                 else if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_MULTIOPT)
366                         optc = '*';
367         }
368
369         r_memset(buf, 0, bufsize);
370
371         start = rpa_recordtree_get(records, rec, RPA_RECORD_START);
372         end = rpa_recordtree_get(records, rec, RPA_RECORD_END);
373         first = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START);
374         last = rpa_recordtree_lastchild(records, rec, RPA_RECORD_START);
375         next = rpa_recordtree_next(records, rec, RPA_RECORD_START);
376         prev = rpa_recordtree_prev(records, rec, RPA_RECORD_START);
377         parent = rpa_recordtree_parent(records, rec, RPA_RECORD_START);
378
379 //      n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "%5d  ( %7ld, %4d ) : ", rec, prec->ruleid, (ruint32)prec->ruleuid);
380         n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "%5ld, n:%5ld (s: %5ld, e: %5ld, p: %5ld) ( %4d, 0x%03x ) : ", rec, prec->next, start, end, parent, prec->ruleuid, prec->usertype);
381         if (prec->type & RPA_RECORD_START)
382                 n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "START ");
383         if (prec->type & RPA_RECORD_END)
384                 n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "END   ");
385         if (prec->type & RPA_RECORD_HEAD)
386                 n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "HEAD ");
387         if (prec->type & RPA_RECORD_TAIL)
388                 n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "TAIL ");
389         n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "%s ", prec->rule);
390
391         r_memset(buf + n, ' ', bufsize - n);
392         n = 115;
393         n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, " %5d, %3d", prec->top, prec->size);
394
395         r_memset(buf + n, ' ', bufsize - n);
396         n = 130;
397         n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, " %c %c %c", optc,
398                         (prec->usertype & RPA_LOOP_PATH) ? 'L' : ' ', (prec->usertype & RPA_NONLOOP_PATH) ? 'N' : ' ');
399         n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, " : ");
400         size = prec->inputsiz;
401         if (size >= bufsize - n - 1)
402                 size = bufsize - n - 1;
403         if (prec->type & RPA_RECORD_END) {
404                 r_strncpy(buf + n, prec->input, size);
405                 n += size;
406                 buf[n] = '\0';
407         }
408
409         r_printf("%s\n", buf);
410 }
411
412
413 void rpa_record_dumpindented(rarray_t *records, rlong rec, rint level)
414 {
415         rchar buffer[1024];
416         rparecord_t *prec;
417         rint i, size;
418
419         if (rec < 0 || rec >= r_array_length(records))
420                 return;
421         r_memset(buffer, 0, sizeof(buffer));
422         prec = (rparecord_t *)r_array_slot(records, rec);
423         for (i = 0; i < level; i++)
424                 r_printf("   ");
425         r_printf("   ");
426         r_printf("(");
427         r_printf("%s, %c, %c", prec->rule, rpa_record_optchar(prec, 'x'), rpa_record_loopchar(prec, 'x'));
428         r_printf(")");
429         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
430         prec = (rparecord_t *)r_array_slot(records, rec);
431         size = R_MIN(prec->inputsiz, sizeof(buffer) - 1);
432         r_strncpy(buffer, prec->input, size);
433
434         if (size == (sizeof(buffer) - 1))
435                 r_printf(" %s ...\n", buffer);
436         else
437                 r_printf(" %s\n", buffer);
438         return;
439 }