RPA Toolkit
build loop info
authorMartin Stoilov <martin@rpasearch.com>
Tue, 22 Mar 2011 05:03:17 +0000 (22:03 -0700)
committerMartin Stoilov <martin@rpasearch.com>
Tue, 22 Mar 2011 05:03:17 +0000 (22:03 -0700)
arch/linux/x86_64/rtypes.h
rpa2/rpaparseinfo.c
rpa2/rpaparseinfo.h
rpa2/rpaparser.c
rpa2/rparecord.c
rpa2/rparecord.h
rpa2/rpavm.h

index 1f3dedc..fc289a2 100644 (file)
@@ -85,5 +85,13 @@ typedef struct {ruint32 p1; ruint32 p2;} rpair_t;
 #endif
 
 
+typedef enum {
+       RVALSET_NONE = 0,
+       RVALSET_OR,
+       RVALSET_XOR,
+       RVALSET_AND,
+} rvalset_t;
+
+
 #endif
 
index c2eece2..3c9f753 100644 (file)
@@ -3,33 +3,81 @@
 #include "rpaparseinfo.h"
 
 
-static int rpa_parseinfo_buildrefinfo_for_rule(rpa_parseinfo_t *pi, rpastat_t *stat, const char *name, ruint namesiz)
+
+static rint rpa_parseinfo_checkforloop(rpa_parseinfo_t *pi, rlong rec, rlong loopstartrec, rlong loopendrec, rint inderction)
 {
-       ruint i;
-       rpa_ruleinfo_t *info, *refinfo;
-       rparecord_t *rec;
-
-       info = (rpa_ruleinfo_t *)r_harray_get(pi->rules, r_harray_lookup(pi->rules, name, namesiz));
-       if (!info)
-               return -1;
-       info->startref = r_array_length(pi->refs);
-       for (i = info->startrec; i < info->sizerecs; i++) {
-               rec = (rparecord_t *)r_array_slot(stat->records, i);
-               if ((rec->userid == RPA_PRODUCTION_AREF) && (rec->type & RPA_RECORD_END)) {
-                       refinfo = (rpa_ruleinfo_t *)r_harray_get(pi->rules, r_harray_lookup(pi->rules, rec->input, rec->inputsiz));
-                       r_array_add(pi->refs, &refinfo->startrec);
+       rlong nrec, i;
+       rint lret, ret = 0;
+
+       if (rec == loopstartrec && inderction > 0)
+               return 1;
+
+       for (i = 0; i < r_array_length(pi->recstack); i++) {
+               if (rec == r_array_index(pi->recstack, i, rlong))
+                       return 0;
+       }
+
+       r_array_add(pi->recstack, &rec);
+
+       for (i = rpa_recordtree_firstchild(pi->records, rec, RPA_RECORD_START); i >= 0; i = rpa_recordtree_next(pi->records, i, RPA_RECORD_START)) {
+               rparecord_t *prec = (rparecord_t *)r_array_slot(pi->records, i);
+               if (prec->userid == RPA_PRODUCTION_AREF || prec->userid == RPA_PRODUCTION_AREF) {
+                       nrec = rpa_recordtree_firstchild(pi->records, i, RPA_RECORD_END);
+                       if (nrec > 0) {
+                               rpa_ruleinfo_t *info;
+                               prec = (rparecord_t *)r_array_slot(pi->records, nrec);
+                               info = (rpa_ruleinfo_t *)r_harray_get(pi->rules, r_harray_lookup(pi->rules, prec->input, prec->inputsiz));
+                               if (info) {
+                                       lret = rpa_parseinfo_checkforloop(pi, info->startrec, loopstartrec, loopendrec, inderction + 1);
+                                       if (i >= loopstartrec && i <= loopendrec && lret) {
+                                               rpa_record_setusertype(pi->records, i, RPA_LOOP_PATH, RVALSET_OR);
+                                               rpa_record_setusertype(pi->records, nrec, RPA_LOOP_PATH, RVALSET_OR);
+                                       }
+                                       ret |= lret;
+                               }
+                       }
+               } else {
+                       lret = rpa_parseinfo_checkforloop(pi, i, loopstartrec, loopendrec, inderction + 1);
+                       if (i >= loopstartrec && i <= loopendrec && lret) {
+                               rpa_record_setusertype(pi->records, i, RPA_LOOP_PATH, RVALSET_OR);
+                               ret |= lret;
+                       }
+
                }
        }
-       info->sizerefs = r_array_length(pi->refs) - info->startref;
-       return 0;
+
+       r_array_removelast(pi->recstack);
+       return ret;
 }
 
 
-static void rpa_parseinfo_buildrefinfo(rpa_parseinfo_t *pi)
+static void rpa_parseinfo_buildloopinfo(rpa_parseinfo_t *pi)
 {
-       ruint i;
+       ruint i, p;
        rharray_t *rules = pi->rules;
+       rpa_ruleinfo_t *info;
+
+       for (i = 0; i < r_array_length(rules->members); i++) {
+               info = (rpa_ruleinfo_t *)r_harray_get(rules, i);
+               if (rpa_parseinfo_checkforloop(pi, info->startrec, info->startrec, info->startrec + info->sizerecs - 1, 0)) {
+                       rpa_record_setusertype(pi->records, info->startrec, RPA_LOOP_PATH, RVALSET_OR);
+               }
+       }
 
+       /*
+        * Mark the non-loop branches.
+        */
+       for (i = 0; i < r_array_length(pi->records); i++) {
+               rparecord_t *prec = (rparecord_t *)r_array_slot(pi->records, i);
+               if (prec->type == RPA_RECORD_START && prec->userid == RPA_PRODUCTION_ALTBRANCH && (prec->usertype & RPA_LOOP_PATH) == 0) {
+                       p = rpa_recordtree_parent(pi->records, i, RPA_RECORD_START);
+                       if (p >= 0) {
+                               prec = (rparecord_t *)r_array_slot(pi->records, p);
+                               if (prec && (prec->usertype & RPA_LOOP_PATH))
+                                       rpa_record_setusertype(pi->records, i, RPA_NONLOOP_PATH, RVALSET_OR);
+                       }
+               }
+       }
 }
 
 
@@ -67,24 +115,60 @@ static void rpa_parseinfo_buildruleinfo(rpa_parseinfo_t *pi)
 }
 
 
-rpa_parseinfo_t *rpa_parseinfo_create(rpastat_t *stat)
+static void rpa_parseinfo_copyrecords(rpa_parseinfo_t *pi, rpastat_t *stat)
 {
        rint i;
-       rpa_parseinfo_t *pi;
        rparecord_t *prec;
 
+       for (i = 0; i < r_array_length(stat->records); i++) {
+               prec = (rparecord_t *)r_array_slot(stat->records, i);
+               if (prec->userid == RPA_PRODUCTION_OCCURENCE && (prec->type & RPA_RECORD_START)) {
+                       /*
+                        * Ignore it
+                        */
+               } else if (prec->userid == RPA_PRODUCTION_OCCURENCE && (prec->type & (RPA_RECORD_MATCH | RPA_RECORD_END))) {
+                       ruint32 usertype = RPA_MATCH_NONE;
+                       rlong lastrec = 0;
+                       /*
+                        * Don't copy it but set the usertype of the previous record accordingly.
+                        */
+                       switch (stat->instack[prec->top].wc) {
+                       case '?':
+                               usertype = RPA_MATCH_OPTIONAL;
+                               break;
+                       case '+':
+                               usertype = RPA_MATCH_MULTIPLE;
+                               break;
+                       case '*':
+                               usertype = RPA_MATCH_MULTIOPT;
+                               break;
+                       default:
+                               usertype = RPA_MATCH_NONE;
+                       };
+                       lastrec = r_array_length(pi->records) - 1;
+                       if (lastrec >= 0)
+                               rpa_record_setusertype(pi->records, lastrec, usertype, RVALSET_OR);
+               } else if (prec->userid != RPA_RECORD_INVALID_UID) {
+                       r_array_add(pi->records, prec);
+               }
+       }
+
+}
+
+
+rpa_parseinfo_t *rpa_parseinfo_create(rpastat_t *stat)
+{
+       rpa_parseinfo_t *pi;
+
        if ((pi = (rpa_parseinfo_t *)r_zmalloc(sizeof(*pi))) == NULL)
                return NULL;
        pi->records = r_array_create(sizeof(rparecord_t));
        pi->rules = r_harray_create(sizeof(rpa_ruleinfo_t));
        pi->refs = r_array_create(sizeof(rulong));
-       for (i = 0; i < r_array_length(stat->records); i++) {
-               prec = (rparecord_t *)r_array_slot(stat->records, i);
-               if (prec->userid != RPA_RECORD_INVALID_UID)
-                       r_array_add(pi->records, prec);
-       }
+       pi->recstack = r_array_create(sizeof(rulong));
+       rpa_parseinfo_copyrecords(pi, stat);
        rpa_parseinfo_buildruleinfo(pi);
-       rpa_parseinfo_buildrefinfo(pi);
+       rpa_parseinfo_buildloopinfo(pi);
        return pi;
 }
 
@@ -93,8 +177,9 @@ void rpa_parseinfo_destroy(rpa_parseinfo_t *pi)
 {
        if (pi) {
                r_object_destroy((robject_t *)pi->records);
-               r_object_destroy((robject_t *)pi->refs);
                r_object_destroy((robject_t *)pi->rules);
+               r_object_destroy((robject_t *)pi->recstack);
+               r_object_destroy((robject_t *)pi->refs);
                r_free(pi);
        }
 }
index db817db..ecf8002 100644 (file)
@@ -23,6 +23,7 @@ typedef struct rpa_parseinfo_s {
        rarray_t *records;
        rharray_t *rules;
        rarray_t *refs;
+       rarray_t *recstack;
 } rpa_parseinfo_t;
 
 
index b23a3b7..0fe5c6c 100644 (file)
@@ -71,6 +71,11 @@ static void rpa_production_bnf(rpa_parser_t *pa)
        rpa_compiler_branch_end(co, RPA_MATCH_NONE);
 
        rpa_compiler_branch_begin(co);
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_production_comment", rvm_asm(RPA_BXLNAN, DA, XX, XX, 0));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rpa_compiler_branch_end(co, RPA_MATCH_NONE);
+
+       rpa_compiler_branch_begin(co);
        rpa_compiler_class_begin(co);
        rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, '\r'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
@@ -93,6 +98,35 @@ static void rpa_production_bnf(rpa_parser_t *pa)
 }
 
 
+static void rpa_production_comment(rpa_parser_t *pa)
+{
+       rpa_compiler_t *co = pa->co;
+
+       rpa_compiler_rule_begin_s(co, "rpa_production_comment");
+
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, '#'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+
+       rpa_compiler_exp_begin(co);
+       rpa_compiler_branch_begin(co);
+       rpa_compiler_class_begin(co);
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, '\r'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, '\n'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, '\0'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
+       rpa_compiler_class_end(co, RPA_MATCH_NONE);
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rpa_compiler_branch_end(co, RPA_MATCH_NONE);
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHSPCHR_NAN, DA, XX, XX, '.'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rpa_compiler_exp_end(co, RPA_MATCH_MULTIOPT);
+
+       rpa_compiler_rule_end(co);
+}
+
+
 static void rpa_production_namedrule(rpa_parser_t *pa)
 {
        rpa_compiler_t *co = pa->co;
@@ -867,16 +901,8 @@ static void rpa_production_negbranch(rpa_parser_t *pa)
        rpa_compiler_add_ruleuid_s(co, "rpa_production_negbranch", RPA_PRODUCTION_NEGBRANCH);
        rpa_compiler_rule_begin_s(co, "rpa_production_negbranch");
 
-       rpa_compiler_exp_begin(co);
-       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_production_space", rvm_asm(RPA_BXLOPT, DA, XX, XX, 0));
-       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, '-'));
-       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
-       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_production_space", rvm_asm(RPA_BXLOPT, DA, XX, XX, 0));
-
        rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_production_exp", rvm_asm(RPA_BXLNAN, DA, XX, XX, 0));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
-       rpa_compiler_exp_end(co, RPA_MATCH_NONE);
-       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
 
        rpa_compiler_rule_end(co);
 }
@@ -889,8 +915,15 @@ static void rpa_production_negexp(rpa_parser_t *pa)
        rpa_compiler_add_ruleuid_s(co, "rpa_production_negexp", RPA_PRODUCTION_NEGEXP);
        rpa_compiler_rule_begin_s(co, "rpa_production_negexp");
 
+       rpa_compiler_exp_begin(co);
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_production_space", rvm_asm(RPA_BXLOPT, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, '-'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_production_space", rvm_asm(RPA_BXLOPT, DA, XX, XX, 0));
+
        rvm_codegen_addrelocins_s(co->cg, RVM_RELOC_JUMP, "rpa_production_negbranch", rvm_asm(RPA_BXLMUL, DA, XX, XX, 0));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rpa_compiler_exp_end(co, RPA_MATCH_MULTIPLE);
 
        rpa_compiler_rule_end(co);
 }
@@ -1061,6 +1094,7 @@ static rint rpa_parser_init(rpa_parser_t *pa)
        rpa_production_assign(pa);
        rpa_production_rulename(pa);
        rpa_production_namedrule(pa);
+       rpa_production_comment(pa);
        rpa_production_bnf(pa);
 
 
index bdafba0..62befe8 100644 (file)
@@ -3,7 +3,6 @@
 #include "rparecord.h"
 
 
-
 rlong rpa_recordtree_get(rarray_t *records, rlong rec, rulong type)
 {
        rlong i, s = 0;
@@ -115,13 +114,87 @@ rlong rpa_recordtree_prev(rarray_t *records, rlong rec, rulong type)
 }
 
 
+rlong rpa_recordtree_parent(rarray_t *records, rlong rec, rulong type)
+{
+       rlong last = -1, parent = -1;
+
+       if (rec < 0)
+               return -1;
+
+       for ( ;rec >= 0; rec = rpa_recordtree_next(records, last, RPA_RECORD_END)) {
+               last = rpa_recordtree_get(records, rec, RPA_RECORD_END);
+       }
+       parent = last + 1;
+       if (parent >= r_array_length(records))
+               return -1;
+       return rpa_recordtree_get(records, parent, type);
+}
+
+
+static void rpa_recordptr_setusertype(rparecord_t *prec, ruint32 usertype, rvalset_t op)
+{
+       switch (op) {
+       case RVALSET_OR:
+               prec->usertype |= usertype;
+               break;
+       case RVALSET_XOR:
+               prec->usertype ^= usertype;
+               break;
+       case RVALSET_AND:
+               prec->usertype &= usertype;
+               break;
+       default:
+               prec->usertype = usertype;
+       }
+}
+
+
+void rpa_record_setusertype(rarray_t *records, rlong rec, ruint32 usertype, rvalset_t op)
+{
+       rparecord_t *prec;
+
+       rec = rpa_recordtree_get(records, rec, RPA_RECORD_START);
+       if (rec >= r_array_length(records))
+               return;
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rpa_recordptr_setusertype(prec, usertype, op);
+       rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
+       if (rec >= r_array_length(records))
+               return;
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rpa_recordptr_setusertype(prec, usertype, op);
+}
+
+
+rlong rpa_record_getusertype(rarray_t *records, rlong rec)
+{
+       rparecord_t *prec;
+
+       rec = rpa_recordtree_get(records, rec, RPA_RECORD_START);
+       if (rec >= r_array_length(records))
+               return -1;
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       return prec->usertype;
+}
+
+
 void rpa_record_dump(rarray_t *records, rlong rec)
 {
        rparecord_t *prec = (rparecord_t *)r_array_slot(records, rec);
-       rlong start, end, first, last, next, prev;
+       rlong start, end, first, last, next, prev, parent;
        rchar buf[240];
        rint bufsize = sizeof(buf) - 1;
        rint n = 0, size;
+       rchar optc = ' ';
+
+       if (prec->type & RPA_RECORD_END) {
+               if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_OPTIONAL)
+                       optc = '?';
+               else if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_MULTIPLE)
+                       optc = '+';
+               else if ((prec->usertype & RPA_MATCH_MASK) == RPA_MATCH_MULTIOPT)
+                       optc = '*';
+       }
 
        r_memset(buf, 0, bufsize);
 
@@ -131,9 +204,10 @@ void rpa_record_dump(rarray_t *records, rlong rec)
        last = rpa_recordtree_lastchild(records, rec, RPA_RECORD_START);
        next = rpa_recordtree_next(records, rec, RPA_RECORD_START);
        prev = rpa_recordtree_prev(records, rec, RPA_RECORD_START);
+       parent = rpa_recordtree_parent(records, rec, RPA_RECORD_START);
 
 //     n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "%5d  ( %7ld, %4d ) : ", rec, prec->ruleid, (ruint32)prec->userid);
-       n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "%5ld (s: %3ld, e: %3ld, f: %3ld, l: %3ld, n: %3ld, p: %3ld) ( %7d, %4d ) : ", rec, start, end, first, last, next, prev, prec->ruleid, (ruint32)prec->userid);
+       n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "%5ld (s: %3ld, e: %3ld, pp: %3ld, f: %3ld, l: %3ld, n: %3ld, p: %3ld) ( %4d, 0x%03x ) : ", rec, start, end, parent, first, last, next, prev, prec->userid, prec->usertype);
        if (prec->type & RPA_RECORD_START)
                n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, "START ");
        if (prec->type & RPA_RECORD_MATCH)
@@ -148,12 +222,13 @@ void rpa_record_dump(rarray_t *records, rlong rec)
 
        r_memset(buf + n, ' ', bufsize - n);
        n = 140;
+       n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, " : %c %c %c", optc, (prec->usertype & RPA_LOOP_PATH) ? 'L' : ' ', (prec->usertype & RPA_NONLOOP_PATH) ? 'N' : ' ');
        n += r_snprintf(buf + n, n < bufsize ? bufsize - n : 0, " : ");
        size = prec->inputsiz;
        if (size >= bufsize - n - 1)
                size = bufsize - n - 1;
        if (prec->type & RPA_RECORD_END) {
-               r_strncpy(buf + n, prec->input, prec->inputsiz);
+               r_strncpy(buf + n, prec->input, size);
                n += size;
                buf[n] = '\0';
        }
index 74a3a12..375013c 100644 (file)
@@ -4,6 +4,7 @@
 #include "rtypes.h"
 #include "rarray.h"
 #include "rlist.h"
+#include "rpavm.h"
 
 
 #ifdef __cplusplus
@@ -21,13 +22,15 @@ typedef struct rparecord_s {
        rlist_t head;
        rlink_t lnk;
        const char *rule;
-       ruint32 userid;
        ruint32 ruleid;
        ruint32 top;
        ruint32 size;
        ruint32 type;
        const char *input;
        rsize_t inputsiz;
+       ruint32 userid;
+       ruint32 usertype;
+       rword userdata;
 } rparecord_t;
 
 
@@ -36,8 +39,11 @@ rlong rpa_recordtree_firstchild(rarray_t *records, rlong rec, rulong type);
 rlong rpa_recordtree_lastchild(rarray_t *records, rlong rec, rulong type);
 rlong rpa_recordtree_next(rarray_t *records, rlong rec, rulong type);
 rlong rpa_recordtree_prev(rarray_t *records, rlong rec, rulong type);
+rlong rpa_recordtree_parent(rarray_t *records, rlong rec, rulong type);
 
 void rpa_record_dump(rarray_t *records, rlong rec);
+void rpa_record_setusertype(rarray_t *records, rlong rec, ruint32 usertype, rvalset_t op);
+rlong rpa_record_getusertype(rarray_t *records, rlong rec);
 
 #ifdef __cplusplus
 }
index 06c1438..aedb3bb 100644 (file)
@@ -14,6 +14,10 @@ extern "C" {
 #define RPA_MATCH_MULTIPLE (1 << 0)
 #define RPA_MATCH_OPTIONAL (1 << 1)
 #define RPA_MATCH_MULTIOPT (RPA_MATCH_MULTIPLE | RPA_MATCH_OPTIONAL)
+#define RPA_MATCH_MASK ((1 << 2) - 1)
+#define RPA_LOOP_PATH (1<<3)
+#define RPA_NONLOOP_PATH (1<<4)
+#define RPA_LOOP_INDERECTION 1024
 
 #define R_ARG R7
 #define R_TOP R8