RPA Toolkit
d4c72630ca74fafb40be7af71d688a2c478ea780
[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 void rpa_record_setusertype(rarray_t *records, rlong rec, ruint32 usertype, rvalset_t op)
266 {
267         rparecord_t *prec;
268
269         rec = rpa_recordtree_get(records, rec, RPA_RECORD_START);
270         if (rec >= r_array_length(records))
271                 return;
272         prec = (rparecord_t *)r_array_slot(records, rec);
273         rpa_recordptr_setusertype(prec, usertype, op);
274         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
275         if (rec >= r_array_length(records))
276                 return;
277         prec = (rparecord_t *)r_array_slot(records, rec);
278         rpa_recordptr_setusertype(prec, usertype, op);
279 }
280
281
282 rlong rpa_record_getusertype(rarray_t *records, rlong rec)
283 {
284         rparecord_t *prec;
285
286         rec = rpa_recordtree_get(records, rec, RPA_RECORD_START);
287         if (rec >= r_array_length(records))
288                 return -1;
289         prec = (rparecord_t *)r_array_slot(records, rec);
290         return prec->usertype;
291 }
292
293
294 rint rpa_record_optchar(rparecord_t *prec, rint defc)
295 {
296         rint optc = defc;
297
298         if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_OPTIONAL)
299                 optc = '?';
300         else if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_MULTIPLE)
301                 optc = '+';
302         else if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_MULTIOPT)
303                 optc = '*';
304         else
305                 optc = defc;
306         return optc;
307 }
308
309
310 rint rpa_record_loopchar(rparecord_t *prec, rint defc)
311 {
312         rint loopc = defc;
313
314         if ((prec->usertype & RPA_LOOP_PATH) && (prec->usertype & RPA_NONLOOP_PATH)) {
315                 /*
316                  * This is an error, should never happen
317                  */
318                 loopc = 'R';
319         } else if ((prec->usertype & RPA_LOOP_PATH)) {
320                 loopc = 'L';
321         } else if ((prec->usertype & RPA_NONLOOP_PATH)) {
322                 loopc = 'N';
323         } else {
324                 loopc = defc;
325         }
326         return loopc;
327 }
328
329
330 void rpa_record_dump(rarray_t *records, rlong rec)
331 {
332         rparecord_t *prec;
333         rlong start, end, first, last, next, prev, parent;
334         rchar buf[240];
335         rint bufsize = sizeof(buf) - 1;
336         rint n = 0, size;
337         rchar optc = ' ';
338
339         if (rec < 0 || rec >= r_array_length(records))
340                 return;
341         prec = (rparecord_t *)r_array_slot(records, rec);
342         if (prec->type & RPA_RECORD_END) {
343                 if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_OPTIONAL)
344                         optc = '?';
345                 else if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_MULTIPLE)
346                         optc = '+';
347                 else if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_MULTIOPT)
348                         optc = '*';
349         }
350
351         r_memset(buf, 0, bufsize);
352
353         start = rpa_recordtree_get(records, rec, RPA_RECORD_START);
354         end = rpa_recordtree_get(records, rec, RPA_RECORD_END);
355         first = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START);
356         last = rpa_recordtree_lastchild(records, rec, RPA_RECORD_START);
357         next = rpa_recordtree_next(records, rec, RPA_RECORD_START);
358         prev = rpa_recordtree_prev(records, rec, RPA_RECORD_START);
359         parent = rpa_recordtree_parent(records, rec, RPA_RECORD_START);
360
361 //      n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "%5d  ( %7ld, %4d ) : ", rec, prec->ruleid, (ruint32)prec->ruleuid);
362         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);
363         if (prec->type & RPA_RECORD_START)
364                 n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "START ");
365         if (prec->type & RPA_RECORD_END)
366                 n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "END   ");
367         if (prec->type & RPA_RECORD_HEAD)
368                 n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "HEAD ");
369         if (prec->type & RPA_RECORD_TAIL)
370                 n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "TAIL ");
371         n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "%s ", prec->rule);
372
373         r_memset(buf + n, ' ', bufsize - n);
374         n = 115;
375         n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, " %5d, %3d", prec->top, prec->size);
376
377         r_memset(buf + n, ' ', bufsize - n);
378         n = 130;
379         n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, " %c %c %c", optc,
380                         (prec->usertype & RPA_LOOP_PATH) ? 'L' : ' ', (prec->usertype & RPA_NONLOOP_PATH) ? 'N' : ' ');
381         n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, " : ");
382         size = prec->inputsiz;
383         if (size >= bufsize - n - 1)
384                 size = bufsize - n - 1;
385         if (prec->type & RPA_RECORD_END) {
386                 r_strncpy(buf + n, prec->input, size);
387                 n += size;
388                 buf[n] = '\0';
389         }
390
391         r_printf("%s\n", buf);
392 }
393
394
395 void rpa_record_dumpindented(rarray_t *records, rlong rec, rint level)
396 {
397         rchar buffer[1024];
398         rparecord_t *prec;
399         rint i, size;
400
401         if (rec < 0 || rec >= r_array_length(records))
402                 return;
403         r_memset(buffer, 0, sizeof(buffer));
404         prec = (rparecord_t *)r_array_slot(records, rec);
405         for (i = 0; i < level; i++)
406                 r_printf("   ");
407         r_printf("   ");
408         r_printf("(");
409         r_printf("%s, %c, %c", prec->rule, rpa_record_optchar(prec, 'x'), rpa_record_loopchar(prec, 'x'));
410         r_printf(")");
411         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
412         prec = (rparecord_t *)r_array_slot(records, rec);
413         size = R_MIN(prec->inputsiz, sizeof(buffer) - 1);
414         r_strncpy(buffer, prec->input, size);
415
416         if (size == (sizeof(buffer) - 1))
417                 r_printf(" %s ...\n", buffer);
418         else
419                 r_printf(" %s\n", buffer);
420         return;
421 }