RPA Toolkit
adding RPA library to the project
authorMartin Stoilov <martin@rpasearch.com>
Mon, 15 Nov 2010 03:42:19 +0000 (19:42 -0800)
committerMartin Stoilov <martin@rpasearch.com>
Mon, 15 Nov 2010 03:42:19 +0000 (19:42 -0800)
60 files changed:
arch/linux/x86_64/rpatypes.h [new file with mode: 0644]
build/linux/build.mk
rpa/Makefile [new file with mode: 0644]
rpa/build/linux/rpa.mk [new file with mode: 0644]
rpa/build/linux/x86_64/Makefile [new file with mode: 0644]
rpa/rpacbrecord.c [new file with mode: 0644]
rpa/rpacbrecord.h [new file with mode: 0644]
rpa/rpaclass.c [new file with mode: 0644]
rpa/rpaclass.h [new file with mode: 0644]
rpa/rpaconfig.h [new file with mode: 0644]
rpa/rpadbex.c [new file with mode: 0644]
rpa/rpadbex.h [new file with mode: 0644]
rpa/rpadbexpriv.c [new file with mode: 0644]
rpa/rpadbexpriv.h [new file with mode: 0644]
rpa/rpadebug.c [new file with mode: 0644]
rpa/rpadebug.h [new file with mode: 0644]
rpa/rpaerror.h [new file with mode: 0644]
rpa/rpalist.c [new file with mode: 0644]
rpa/rpalist.h [new file with mode: 0644]
rpa/rpamatch.c [new file with mode: 0644]
rpa/rpamatch.h [new file with mode: 0644]
rpa/rpamatchlist.c [new file with mode: 0644]
rpa/rpamatchlist.h [new file with mode: 0644]
rpa/rpamatchrange.c [new file with mode: 0644]
rpa/rpamatchrange.h [new file with mode: 0644]
rpa/rpamatchrangelist.c [new file with mode: 0644]
rpa/rpamatchrangelist.h [new file with mode: 0644]
rpa/rpamatchspecial.c [new file with mode: 0644]
rpa/rpamatchspecial.h [new file with mode: 0644]
rpa/rpamatchstr.c [new file with mode: 0644]
rpa/rpamatchstr.h [new file with mode: 0644]
rpa/rpamatchval.c [new file with mode: 0644]
rpa/rpamatchval.h [new file with mode: 0644]
rpa/rpamem.c [new file with mode: 0644]
rpa/rpamem.h [new file with mode: 0644]
rpa/rpamnode.c [new file with mode: 0644]
rpa/rpamnode.h [new file with mode: 0644]
rpa/rpaparser.c [new file with mode: 0644]
rpa/rpaparser.h [new file with mode: 0644]
rpa/rpaposmnodestack.c [new file with mode: 0644]
rpa/rpaposmnodestack.h [new file with mode: 0644]
rpa/rpasearch.c [new file with mode: 0644]
rpa/rpasearch.h [new file with mode: 0644]
rpa/rpastat.c [new file with mode: 0644]
rpa/rpastat.h [new file with mode: 0644]
rpa/rpastring.c [new file with mode: 0644]
rpa/rpastring.h [new file with mode: 0644]
rpa/rpatypedef.h [new file with mode: 0644]
rpa/rpautf.c [new file with mode: 0644]
rpa/rpautf.h [new file with mode: 0644]
rpa/rpavar.c [new file with mode: 0644]
rpa/rpavar.h [new file with mode: 0644]
rpa/rpavarlink.c [new file with mode: 0644]
rpa/rpavarlink.h [new file with mode: 0644]
rpa/rpavm.c [new file with mode: 0644]
rpa/rpavm.h [new file with mode: 0644]
rpa/rpawordstack.c [new file with mode: 0644]
rpa/rpawordstack.h [new file with mode: 0644]
rvm/config/rvmconfig.h
tests/build/linux/robject-tests.mk

diff --git a/arch/linux/x86_64/rpatypes.h b/arch/linux/x86_64/rpatypes.h
new file mode 100644 (file)
index 0000000..533b880
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPADEF_H_
+#define _RPADEF_H_
+
+
+typedef unsigned long rpa_word_t;
+typedef long rpa_sword_t;
+typedef unsigned short rpa_wchar_t;
+
+#ifndef NULL\r
+#ifdef __cplusplus\r
+#define NULL 0\r
+#else\r
+#define NULL ((void *)0)\r
+#endif\r
+#endif
+
+#endif
index d6c3953..a6fc860 100644 (file)
@@ -1,14 +1,17 @@
 all:
        make -C $(SRCDIR)/rlib/build/$(OS)/$(ARCHDIR) all
+       make -C $(SRCDIR)/rpa/build/$(OS)/$(ARCHDIR) all
        make -C $(SRCDIR)/rvm/build/$(OS)/$(ARCHDIR) all
        make -C $(SRCDIR)/tests/build/$(OS)/$(ARCHDIR) all
 
 distclean: clean
        make -C $(SRCDIR)/rlib/build/$(OS)/$(ARCHDIR) distclean
+       make -C $(SRCDIR)/rpa/build/$(OS)/$(ARCHDIR) distclean
        make -C $(SRCDIR)/rvm/build/$(OS)/$(ARCHDIR) distclean
        make -C $(SRCDIR)/tests/build/$(OS)/$(ARCHDIR) distclean
 
 clean:
        make -C $(SRCDIR)/rlib/build/$(OS)/$(ARCHDIR) clean
+       make -C $(SRCDIR)/rpa/build/$(OS)/$(ARCHDIR) clean
        make -C $(SRCDIR)/rvm/build/$(OS)/$(ARCHDIR) clean
        make -C $(SRCDIR)/tests/build/$(OS)/$(ARCHDIR) clean
diff --git a/rpa/Makefile b/rpa/Makefile
new file mode 100644 (file)
index 0000000..ec3b3cb
--- /dev/null
@@ -0,0 +1,19 @@
+all: $(OUTDIR) $(BNF_LIB)
+       make -C make/unix
+
+distclean: clean
+       make -C make/unix clean
+
+
+clean:
+       make -C make/unix distclean
+
+
+sdk:
+       make -C make/unix sdk
+
+install:
+       make -C make/unix install
+
+uninstall:
+       make -C make/unix uninstall
diff --git a/rpa/build/linux/rpa.mk b/rpa/build/linux/rpa.mk
new file mode 100644 (file)
index 0000000..d213067
--- /dev/null
@@ -0,0 +1,87 @@
+RPA_SRCDIR = $(SRCDIR)/rpa
+
+
+RPA_LIBNAME = librpa
+RPASX_LIBNAME = librpasx
+RPA_LIB = $(OUTDIR)/$(RPA_LIBNAME).a
+RPA_SO = $(OUTDIR)/$(RPA_LIBNAME).so.1.0
+RPASX_LIB = $(OUTDIR)/$(RPASX_LIBNAME).a
+RPASX_SO = $(OUTDIR)/$(RPASX_LIBNAME).so.1.0
+
+CFLAGS += -I$(RPA_SRCDIR)/config -I$(SRCDIR)/rlib
+CFLAGS += -DRPA_DEBUG_MEM 
+CFLAGS += -DHAVESTDIO
+#CFLAGS += -DDEBUGPRINT
+#CFLAGS += -DCODEGENDEBUG
+#CFLAGS += -DVMEXECDEBUG 
+#CFLAGS += -DRPANOSTACKCHEK
+
+
+
+RPA_OBJECTS = \
+       $(OUTDIR)/rpaclass.o \
+       $(OUTDIR)/rpautf.o \
+       $(OUTDIR)/rpamem.o \
+       $(OUTDIR)/rpastring.o \
+       $(OUTDIR)/rpamnode.o \
+       $(OUTDIR)/rpamatch.o \
+       $(OUTDIR)/rpamatchspecial.o \
+       $(OUTDIR)/rpamatchrangelist.o \
+       $(OUTDIR)/rpamatchval.o \
+       $(OUTDIR)/rpamatchlist.o \
+       $(OUTDIR)/rpamatchstr.o \
+       $(OUTDIR)/rpamatchrange.o \
+       $(OUTDIR)/rpastat.o \
+       $(OUTDIR)/rpavar.o \
+       $(OUTDIR)/rpavarlink.o \
+       $(OUTDIR)/rpadebug.o \
+       $(OUTDIR)/rpaparser.o \
+       $(OUTDIR)/rpavm.o \
+       $(OUTDIR)/rpawordstack.o \
+       $(OUTDIR)/rpaposmnodestack.o \
+       $(OUTDIR)/rpadbex.o \
+       $(OUTDIR)/rpadbexpriv.o \
+       $(OUTDIR)/rpacbrecord.o
+
+RPASX_OBJECTS =        \
+       $(OUTDIR)/rpasearch.o \
+
+
+
+ifeq ($(OS), linux)
+all: $(OUTDIR) $(RPA_LIB) $(RPA_SO) $(RPASX_LIB) $(RPASX_SO)
+else
+all: $(OUTDIR) $(RPA_LIB) $(RPASX_LIB)
+endif
+
+
+$(OUTDIR)/%.o: $(RPA_SRCDIR)/%.c
+       $(CC) $(CFLAGS) -o $(OUTDIR)/$*.o -c $(RPA_SRCDIR)/$*.c
+
+$(RPA_LIB): $(RPA_OBJECTS)
+       $(AR) -cr $@ $^
+
+$(RPA_SO): $(RPA_OBJECTS)
+       $(CC) $(LDFLAGS) -shared -Wl,-soname,librpa.so -o $@ $^
+
+$(RPASX_LIB): $(RPASX_OBJECTS)
+       $(AR) -cr $@ $^
+
+$(RPASX_SO): $(RPASX_OBJECTS)
+       $(CC) $(LDFLAGS) -shared -Wl,-soname,$(RPASX_LIBNAME).so -o $(RPASX_SO) $^
+
+
+$(OUTDIR):
+       @mkdir $(OUTDIR)
+
+distclean: clean
+       @rm -f .depend
+       @rm -rf $(OUTDIR)
+
+clean:
+       @rm -f $(RPA_LIB)
+       @rm -f $(RPA_SO)
+       @rm -f $(RPA_OBJECTS)
+       @rm -f *~
+       @rm -f $(SRCDIR)/*~
+
diff --git a/rpa/build/linux/x86_64/Makefile b/rpa/build/linux/x86_64/Makefile
new file mode 100644 (file)
index 0000000..97a97dc
--- /dev/null
@@ -0,0 +1,26 @@
+SRCDIR = ../../../..
+ARCHDIR = $(shell basename $(shell pwd))
+OUTDIR = out
+OS = $(shell uname | tr "[:upper:]" "[:lower:]")
+INCLUDE = -I$(SRCDIR)/arch/$(OS)/$(ARCHDIR)
+
+CC = gcc
+AR = ar
+LD = ld
+
+ifeq ($(BLDCFG), release)
+CFLAGS := -fPIC -O3
+else
+CFLAGS := -fPIC -O0 -ggdb -Wall -DDEBUG
+endif
+
+ifeq ($(CCBLD), yes)
+CFLAGS += -fprofile-arcs -ftest-coverage
+endif
+
+
+CFLAGS += $(MACH) $(INCLUDE)
+LDFLAGS := $(MACH)
+
+
+include ../rpa.mk
diff --git a/rpa/rpacbrecord.c b/rpa/rpacbrecord.c
new file mode 100644 (file)
index 0000000..d88411e
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+
+#include "rpacbrecord.h"
+#include "rpamem.h"
+#include "rpatypes.h"
+
+
+#define RPA_CBSET_GROW 128
+
+rpa_cbset_t *rpa_cbset_init(rpa_cbset_t *cbset)
+{
+       rpa_memset(cbset, 0, sizeof(*cbset));
+       if (rpa_cbset_check_space(cbset) < 0)
+               return (void*)0;
+       return cbset;
+}
+
+
+void rpa_cbset_cleanup(rpa_cbset_t *cbset)
+{
+       rpa_free(cbset->data);
+}
+
+
+int rpa_cbset_check_space(rpa_cbset_t *cbset)
+{
+       rpa_cbrecord_t *data;
+       rpa_word_t size;
+
+       if (cbset->size - cbset->off < RPA_CBSET_GROW) {
+               size = cbset->size + RPA_CBSET_GROW;
+               data = (rpa_cbrecord_t *)rpa_realloc(cbset->data, (unsigned long)(sizeof(rpa_cbrecord_t) * size));
+               if (!data)
+                       return -1;
+               cbset->size = size;
+               cbset->data = data;
+       }
+       return 0;
+}
+
+
+rpa_cbrecord_t *rpa_cbset_push(rpa_cbset_t *cbset)
+{
+       if (rpa_cbset_check_space(cbset) < 0)
+               return (void*)0;
+       cbset->off += 1;
+       return &cbset->data[cbset->off];
+}
+
+
+void rpa_cbset_reset(rpa_cbset_t *cbset, rpa_word_t off)
+{
+       cbset->off = off;
+}
+
+
+rpa_word_t rpa_cbset_getpos(rpa_cbset_t *cbset)
+{
+       return cbset->off;
+}
+
diff --git a/rpa/rpacbrecord.h b/rpa/rpacbrecord.h
new file mode 100644 (file)
index 0000000..3b3cc54
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPACBRECORD_H_
+#define _RPACBRECORD_H_
+
+#include "rpamatch.h"
+#include "rpamnode.h"
+#include "rpatypedef.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct rpa_cbrecord_s {
+       rpa_mnode_t *mnode;
+       const char *input;
+       unsigned int size;
+} rpa_cbrecord_t;
+
+
+typedef struct rpa_cbset_s {
+       rpa_cbrecord_t *data;
+       rpa_word_t size;
+       rpa_word_t off;
+} rpa_cbset_t;
+
+rpa_cbset_t *rpa_cbset_init(rpa_cbset_t *cbset);
+void rpa_cbset_cleanup(rpa_cbset_t *cbset);
+int rpa_cbset_check_space(rpa_cbset_t *cbset);
+rpa_cbrecord_t *rpa_cbset_push(rpa_cbset_t *cbset);
+void rpa_cbset_reset(rpa_cbset_t *cbset, rpa_word_t off);
+rpa_word_t rpa_cbset_getpos(rpa_cbset_t *cbset);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpa/rpaclass.c b/rpa/rpaclass.c
new file mode 100644 (file)
index 0000000..8c201d4
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include "rpaclass.h"
+
+
+const char *rpa_class_to_str(rpa_class_t *cls)
+{
+       return "unk";
+}
+
+
+void rpa_class_init(rpa_class_t *cls, rpa_class_methods_t *vptr)
+{
+       cls->vptr = vptr;       
+}
+
+
+unsigned int rpa_class_getid(rpa_class_t *cls)
+{
+       return cls->vptr->rpa_class_getid(cls); 
+}
+
+
+const char *rpa_class_getstr(rpa_class_t *cls)
+{
+       return cls->vptr->rpa_class_getstr(cls);        
+}
+
+
+int rpa_class_dump(rpa_class_t *cls, char *buffer, unsigned int size)
+{
+       return cls->vptr->rpa_class_dump(cls, buffer, size);    
+}
+
+
+void rpa_class_destroy(rpa_class_t *cls)
+{
+       cls->vptr->rpa_class_destroy(cls);
+}
diff --git a/rpa/rpaclass.h b/rpa/rpaclass.h
new file mode 100644 (file)
index 0000000..3de715d
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPACLASS_H_
+#define _RPACLASS_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define RPA_MATCH_CLASSID                              (1<<0)
+#define RPA_MATCH_SPECIAL_CLASSID              (1<<1)
+#define RPA_MATCH_VAL_CLASSID                  (1<<2)
+#define RPA_MATCH_RANGE_CLASSID                        (1<<3)
+#define RPA_MATCH_RANGELIST_CLASSID            (1<<4)
+#define RPA_MATCH_STR_CLASSID                  (1<<5)
+#define RPA_MATCH_LIST_CLASSID                 (1<<6)
+#define RPA_MATCH_NLIST_CLASSID                        (1<<7)
+#define RPA_MNODE_CLASSID                              (1<<8)
+#define RPA_HASHENTRY_CLASSID                  (1<<9)
+#define RPA_RESERVED1_CLASSID                  (1<<24)
+#define RPA_RESERVED2_CLASSID                  (1<<25)
+#define RPA_RESERVED3_CLASSID                  (1<<26)
+#define RPA_RESERVED4_CLASSID                  (1<<27)
+#define RPA_RESERVED5_CLASSID                  (1<<28)
+#define RPA_RESERVED6_CLASSID                  (1<<29)
+#define RPA_RESERVED7_CLASSID                  (1<<30)
+#define RPA_RESERVED8_CLASSID                  (1<<31)
+
+
+typedef struct rpa_class_s rpa_class_t;
+
+typedef struct rpa_class_methods_s {
+       unsigned int (*rpa_class_getid)(rpa_class_t *cls);
+       const char* (*rpa_class_getstr)(rpa_class_t *cls);
+       int (*rpa_class_dump)(rpa_class_t *cls, char *buffer, unsigned int size);
+       void (*rpa_class_destroy)(rpa_class_t *cls);    
+} rpa_class_methods_t;
+
+
+struct rpa_class_s {
+       rpa_class_methods_t *vptr;
+};
+
+
+void rpa_class_init(rpa_class_t *cls, rpa_class_methods_t *vptr);
+unsigned int rpa_class_getid(rpa_class_t *cls);
+const char *rpa_class_getstr(rpa_class_t *cls);
+int rpa_class_dump(rpa_class_t *cls, char *buffer, unsigned int size);
+void rpa_class_destroy(rpa_class_t *cls);
+
+
+const char *rpa_class_to_str(rpa_class_t *cls);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpa/rpaconfig.h b/rpa/rpaconfig.h
new file mode 100644 (file)
index 0000000..80f2453
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPACONFIG_H_
+#define _RPACONFIG_H_
+
+#define RPA_VERSION_STRING "1.0.3-pre"
+#define RPA_LOOPHASH_BITS 8
+#define RPA_MAXSTACK_SIZE (64 * 1024 * sizeof(void*))
+
+
+#endif
diff --git a/rpa/rpadbex.c b/rpa/rpadbex.c
new file mode 100644 (file)
index 0000000..9448861
--- /dev/null
@@ -0,0 +1,604 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include "rpamnode.h"
+#include "rpamem.h"
+#include "rpastring.h"
+#include "rpamatch.h"
+#include "rpadbexpriv.h"
+#include "rpadbex.h"
+#include "rpamatchstr.h"
+#include "rpamatchrange.h"
+#include "rpamatchval.h"
+#include "rpamatchlist.h"
+#include "rpadebug.h"
+#include "rpaerror.h"
+#include "rpalist.h"
+#include "rpasearch.h"
+
+
+typedef struct rpa_match_s rpa_pattern_s;
+typedef struct rpa_match_s rpa_group_s;
+
+
+void rpa_dbex_close_do(rpa_dbex_handle hDbex)
+{
+       rpa_head_t mhead = RPA_LIST_HEAD(mhead);
+       rpa_pattern_handle hPattern = ((void*)0);
+       rpa_mnode_t mnode;
+
+       if (!hDbex)
+               return;
+       
+       rpa_memset(&mnode, 0, sizeof(mnode));
+       for (hPattern = rpa_dbex_first_pattern(hDbex); hPattern; hPattern = rpa_dbex_next_pattern(hDbex, hPattern)) {
+               mnode.match = (rpa_match_t *)hPattern->var.v.ptr;
+               mnode.flags = 0;
+
+               if (rpa_mnode_check_for_loop(&mnode, mnode.match, &mhead, 0))
+                       ((rpa_match_nlist_t*)(mnode.match))->loopy = 1;
+       }
+
+       hDbex->rwlock = 0;
+}
+
+
+void rpa_dbex_close(rpa_dbex_handle hDbex)
+{
+       rpa_dbex_close_do(hDbex);
+       rpa_dbex_connect_callbacks(hDbex);
+}
+
+
+void rpa_dbex_cleanup(rpa_dbex_handle hDbex)
+{
+       rpa_varlink_destroy_all(&hDbex->treehead);
+       rpa_free(hDbex->namehash);
+       if (hDbex->parser)
+               rpa_parser_destroy(hDbex->parser);
+       if (hDbex->parser)
+               rpa_vm_destroy(hDbex->vm);
+       rpa_stat_cleanup(&hDbex->stat);
+}
+
+rpa_dbex_handle rpa_dbex_init(rpa_dbex_handle hDbex, unsigned int namehashEntries)
+{
+       unsigned int i;
+       if (namehashEntries < 2)
+               namehashEntries = 2;
+       for (i = 0; namehashEntries; i++)
+               namehashEntries >>= 1;
+       namehashEntries = 1 << (i - 1);
+       rpa_memset(hDbex, 0, sizeof(*hDbex));
+       rpa_list_init(&hDbex->treehead);
+       rpa_list_init(&hDbex->callbacks);
+       rpa_list_init(&hDbex->callbackmnodes);
+       hDbex->namehashEntries = namehashEntries;
+       hDbex->namehash = rpa_malloc(namehashEntries* sizeof(rpa_head_t));
+       for (i = 0; i < namehashEntries; i++)
+               rpa_list_init(&hDbex->namehash[i]);
+       if (rpa_dbex_check_parser(hDbex) < 0) {
+               rpa_dbex_cleanup(hDbex);
+               return (void*)0;
+       }
+       if (rpa_dbex_check_vm(hDbex) < 0) {
+               rpa_dbex_cleanup(hDbex);
+               return (void*)0;
+       }
+       rpa_stat_init(&hDbex->stat);
+       if (rpa_dbex_int_ascii_matchptr_array(hDbex) < 0) {
+               rpa_dbex_cleanup(hDbex);
+               return (void*)0;
+       }
+       return hDbex;
+}
+
+
+rpa_dbex_handle rpa_dbex_create_with_hash(unsigned int uHashEntries)
+{
+       rpa_dbex_handle hDbex;
+
+       if (!(hDbex = rpa_malloc(sizeof(*hDbex))))
+               return ((void*)0);
+       return rpa_dbex_init(hDbex, uHashEntries);
+}
+
+
+rpa_dbex_handle rpa_dbex_create(void)
+{
+       return rpa_dbex_create_with_hash(RPA_NAMEHASH_SIZE);
+}
+
+
+void rpa_dbex_destroy(rpa_dbex_handle hDbex)
+{
+       rpa_dbex_cleanup(hDbex);
+       rpa_free((void *)hDbex);
+}
+
+
+int rpa_dbex_load(rpa_dbex_handle hDbex, const char *patterns, unsigned int size)
+{
+       int ret = 0, vmret = 0;
+       
+       if (!hDbex)
+               return -1;
+       if (!hDbex->rwlock) {
+               hDbex->lastError = RPA_E_NOTOPEN;
+               return -1;
+       }
+       if (!patterns) {
+               hDbex->lastError = RPA_E_INVALID_PARAM;
+               return -1;
+       }
+       if (size == 0) {
+               return 0;
+       }
+
+       rpa_stat_set_encoding(&hDbex->parser->stat, RPA_ENCODING_UTF8);
+       ret = rpa_parser_exec(hDbex->parser, patterns, size);
+       if (ret == 0) {
+               hDbex->lastError = RPA_E_SYNTAX_ERROR;
+               return -1;
+       }
+       if (hDbex->parser->vmcode_off) {
+#ifdef VMEXECDEBUG
+               vmret = rpa_vm_exec_debug(hDbex->vm, hDbex->parser->vmcode, 0);
+#else
+               vmret = rpa_vm_exec(hDbex->vm, hDbex->parser->vmcode, 0);
+               if (vmret < 0) {
+                       hDbex->lastError = RPA_E_SYNTAX_ERROR;
+                       return -1;
+               }
+#endif
+               
+       }
+       return ret;
+}
+
+
+int rpa_dbex_load_string(rpa_dbex_handle hDbex, const char *patterns)
+{
+       int ret, inputsize;
+
+       if (!patterns) {
+               hDbex->lastError = RPA_E_INVALID_PARAM;
+               return -1;
+       }
+       inputsize = rpa_strlen(patterns) + 1;
+       while ((ret = rpa_dbex_load(hDbex, patterns, inputsize)) > 0) {
+               inputsize -= ret;
+               patterns += ret;
+       }
+       return ret;
+}
+
+
+int rpa_dbex_open(rpa_dbex_handle hDbex)
+{
+       if (!hDbex)
+               return -1;
+       hDbex->rwlock = 1;
+       return 0;
+}
+
+
+rpa_pattern_handle rpa_dbex_get_pattern(rpa_dbex_handle hDbex, const char *name)
+{
+       rpa_pattern_handle hPattern = ((void*)0);
+       const char *patternName;
+
+       for (hPattern = rpa_dbex_first_pattern(hDbex); hPattern; hPattern = rpa_dbex_next_pattern(hDbex, hPattern)) {
+               patternName = rpa_dbex_pattern_name(hDbex, hPattern);
+               if (rpa_dbex_pattern_name(hDbex, hPattern) && rpa_strcmp(patternName, name) == 0)
+                       return hPattern;
+       }
+       return ((void *)0);
+}
+
+
+rpa_pattern_handle rpa_dbex_default_pattern(rpa_dbex_handle hDbex)
+{
+       if (hDbex)
+               return hDbex->defaultPattern;
+       return (void*)0;
+}
+
+
+unsigned int rpa_dbex_get_error(rpa_dbex_handle hDbex)
+{
+       if (hDbex)
+               return hDbex->lastError;
+       return RPA_E_NONE;
+}
+
+
+rpa_pattern_handle rpa_dbex_next_pattern(rpa_dbex_handle hDbex, rpa_pattern_handle hCur)
+{
+       rpa_link_t *pos;
+       rpa_varlink_t *pVarLinkMatch;
+
+       for (pos = rpa_list_next(&hDbex->treehead, hCur ? &hCur->lnk : &hDbex->treehead); pos; pos = rpa_list_next(&hDbex->treehead, pos)) {
+               pVarLinkMatch = rpa_list_entry(pos, rpa_varlink_t, lnk);
+               if (pVarLinkMatch->var.userdata4 == MATCH_CLASS_NAMEDMATCHPTR) {
+                       return pVarLinkMatch;
+               }
+       }
+       return ((void *)0);
+}
+
+
+rpa_pattern_handle rpa_dbex_prev_pattern(rpa_dbex_handle hDbex, rpa_pattern_handle hCur)
+{
+       rpa_link_t *pos;
+       rpa_varlink_t *pVarLinkMatch;
+
+       for (pos = rpa_list_prev(&hDbex->treehead, hCur ? &hCur->lnk : &hDbex->treehead); pos; pos = rpa_list_prev(&hDbex->treehead, pos)) {
+               pVarLinkMatch = rpa_list_entry(pos, rpa_varlink_t, lnk);
+               if (pVarLinkMatch->var.userdata4 == MATCH_CLASS_NAMEDMATCHPTR) {
+                       return pVarLinkMatch;
+               }
+       }
+       return ((void *)0);
+}
+
+
+rpa_pattern_handle rpa_dbex_first_pattern(rpa_dbex_handle hDbex)
+{
+       return rpa_dbex_next_pattern(hDbex, 0);
+}
+
+
+rpa_pattern_handle rpa_dbex_last_pattern(rpa_dbex_handle hDbex)
+{
+       return rpa_dbex_prev_pattern(hDbex, 0);
+}
+
+
+const char *rpa_dbex_pattern_name(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern)
+{
+       const char *name = ((void *)0);
+       if (!hDbex)
+               goto error;
+       if (!hPattern) {
+               hDbex->lastError = RPA_E_INVALID_PARAM;
+               goto error;
+       }
+       if (hPattern->var.userdata4 == MATCH_CLASS_NAMEDMATCHPTR) {
+               rpa_match_t *match = (rpa_match_t *)hPattern->var.v.ptr;
+               name = match->name;
+       }
+       
+error:
+       return name;
+}
+
+
+const char *rpa_dbex_pattern_regex(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern, int seq)
+{
+       int count = 0;
+       const char *regex = ((void *)0);
+       
+       if (!hDbex)
+               goto error;
+       if (!hPattern) {
+               hDbex->lastError = RPA_E_INVALID_PARAM;
+               goto error;
+       }
+       if (hPattern->var.userdata4 == MATCH_CLASS_NAMEDMATCHPTR) {
+               rpa_link_t *pos;
+               rpa_mnode_t *mnode;
+               rpa_match_list_t *match = (rpa_match_list_t *)hPattern->var.v.ptr;
+               pos = rpa_list_first(&match->head);
+               for (count = 0; count < seq && pos; count++) {
+                       pos = rpa_list_next(&match->head, pos);
+               }
+               if (pos) {
+                       mnode = rpa_list_entry(pos, rpa_mnode_t, mlink);
+                       regex = mnode->match->name;
+               }
+       } else if (hPattern->var.userdata4 == MATCH_CLASS_MATCHPTR) {
+               rpa_match_t *match = (rpa_match_t *)hPattern->var.v.ptr;
+               regex = match->name;
+       }
+       
+error:
+       return regex;
+}
+
+
+int rpa_dbex_strmatch(const char *str, const char *patterns)
+{
+       struct rpa_dbex_s dbex;
+       int len = 0;
+       int ret = 0;
+       
+       if (patterns == ((void *)0) || patterns == ((void *)0))
+               return -1;
+       len = rpa_strlen(str);
+       rpa_dbex_init(&dbex, 16);
+       while (*patterns) {
+               if ((ret = rpa_dbex_load_string(&dbex, patterns)) < 0)
+                       goto error;
+               if (ret == 0)
+                       break;
+               patterns += ret;
+       }
+       ret = rpa_stat_match_lite(&dbex.stat, rpa_dbex_default_pattern(&dbex), str, str, str + len);
+       if (ret < 0)
+               goto error;
+       rpa_dbex_close_do(&dbex);
+       rpa_dbex_cleanup(&dbex);
+       return ret;
+       
+error:
+       rpa_dbex_cleanup(&dbex);
+       return -1;
+}
+
+
+int rpa_dbex_add_callback(rpa_dbex_handle hDbex, const char *namematch, unsigned int reason, rpa_match_callback func, void *userdata)
+{
+       int ret = 0, cbsize = 0, namesiz = 0;
+       rpa_varlink_t *pVarLinkCallback;
+       rpa_callbackdata_t *pCbData = (void*)0;
+       
+       if (namematch) {
+               namesiz = rpa_strlen(namematch);
+       }
+       cbsize = sizeof(rpa_callbackdata_t) + namesiz + 1;
+       if ((pCbData = (rpa_callbackdata_t *)rpa_malloc(cbsize)) == 0) {
+               hDbex->lastError = RPA_E_OUTOFMEM;
+               return -1;              
+       }
+       rpa_memset(pCbData, 0, cbsize);
+       rpa_strncpy(pCbData->namematch, namematch, namesiz);
+       pCbData->userdata = userdata;
+       pCbData->reason = reason;
+       pCbData->func = func;
+       pVarLinkCallback = rpa_varlink_create(RPA_VAR_PTR, "callback");
+       if (!pVarLinkCallback) {
+               rpa_free(pCbData);
+               hDbex->lastError = RPA_E_OUTOFMEM;
+               return -1;              
+       }
+       pVarLinkCallback->var.userdata4 = (rpa_word_t)MATCH_CLASS_CALLBACKPTR;
+       pVarLinkCallback->var.v.ptr = pCbData;
+       pVarLinkCallback->var.finalize = rpa_var_finalize_ptr;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkCallback->lnk);
+       rpa_list_addt(&hDbex->callbacks, &pVarLinkCallback->hlnk);
+       return ret;     
+}
+
+
+const char *rpa_dbex_callback_pattern(rpa_dbex_handle hDbex, rpa_callback_handle hCallback)
+{
+       if (!hDbex)
+               goto error;
+       if (!hCallback) {
+               hDbex->lastError = RPA_E_INVALID_PARAM;
+               goto error;
+       }
+       if (hCallback->var.userdata4 == MATCH_CLASS_CALLBACKPTR) {
+               return ((rpa_callbackdata_t*)hCallback->var.v.ptr)->namematch;
+       }
+error:
+       return ((void*)0);
+}
+
+
+void *rpa_dbex_callback_userdata(rpa_dbex_handle hDbex, rpa_callback_handle hCallback)
+{
+       rpa_callbackdata_t *pCbData = (void*)0; 
+       if (!hDbex)
+               goto error;
+       if (!hCallback) {
+               hDbex->lastError = RPA_E_INVALID_PARAM;
+               goto error;
+       }
+       if (hCallback->var.userdata4 == MATCH_CLASS_CALLBACKPTR) {
+               pCbData = (rpa_callbackdata_t *)hCallback->var.v.ptr;
+               return (void*)pCbData->userdata;
+       }
+error:
+       return ((void*)0);
+}
+
+
+int rpa_dbex_pattern_type(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern)
+{
+       int type = RPA_PATTERN_SINGLE;
+
+       if (!hDbex)
+               goto error;
+       if (!hPattern) {
+               hDbex->lastError = RPA_E_INVALID_PARAM;
+               goto error;
+       }
+       if (hPattern->var.userdata4 == MATCH_CLASS_NAMEDMATCHPTR) {
+               rpa_match_t *match = (rpa_match_t *)hPattern->var.v.ptr;
+               if (match->match_function_id == RPA_MATCHFUNC_NLIST_ALT)
+                       type = RPA_PATTERN_OR;
+               else if (match->match_function_id == RPA_MATCHFUNC_NLIST_BESTALT)
+                       type = RPA_PATTERN_BEST;
+       }
+       
+error:
+       return type;
+}
+
+
+rpa_varlink_t *rpa_dbex_next_callback(rpa_dbex_handle hDbex, rpa_varlink_t *cur)
+{
+       rpa_link_t *pos;
+       rpa_varlink_t *pVarLinkCallback;
+
+       for (pos = rpa_list_next(&hDbex->callbacks, cur ? &cur->hlnk : &hDbex->callbacks); pos; pos = rpa_list_next(&hDbex->callbacks, pos)) {
+               pVarLinkCallback = rpa_list_entry(pos, rpa_varlink_t, hlnk);
+               if (pVarLinkCallback->var.userdata4 == MATCH_CLASS_CALLBACKPTR) {
+                       return pVarLinkCallback;
+               }
+       }
+       return ((void *)0);
+}
+
+
+rpa_varlink_t *rpa_dbex_prev_callback(rpa_dbex_handle hDbex, rpa_varlink_t *cur)
+{
+       rpa_link_t *pos;
+       rpa_varlink_t *pVarLinkCallback;
+
+       for (pos = rpa_list_prev(&hDbex->callbacks, cur ? &cur->hlnk : &hDbex->callbacks); pos; pos = rpa_list_prev(&hDbex->callbacks, pos)) {
+               pVarLinkCallback = rpa_list_entry(pos, rpa_varlink_t, hlnk);
+               if (pVarLinkCallback->var.userdata4 == MATCH_CLASS_CALLBACKPTR) {
+                       return pVarLinkCallback;
+               }
+       }
+       return ((void *)0);
+}
+
+
+rpa_varlink_t *rpa_dbex_first_callback(rpa_dbex_handle hDbex)
+{
+       return rpa_dbex_next_callback(hDbex, 0);
+}
+
+
+rpa_varlink_t *rpa_dbex_last_callback(rpa_dbex_handle hDbex)
+{
+       return rpa_dbex_prev_callback(hDbex, 0);        
+}
+
+
+int rpa_dbex_scan(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern, const char *input, const char *start, const char *end, const char **where)
+{
+    if (!hDbex)
+        return -1;
+    if (!hPattern || !input || !start || !end) {
+        hDbex->lastError = RPA_E_INVALID_PARAM;
+        return -1;
+    }
+
+       return rpa_stat_scan(&hDbex->stat, hPattern, input, start, end, where);
+}
+
+
+int rpa_dbex_match(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern, const char *input, const char *start, const char *end)
+{
+    if (!hDbex)
+        return -1;
+    if (!hPattern || !input || !start || !end) {
+        hDbex->lastError = RPA_E_INVALID_PARAM;
+        return -1;
+    }
+
+       return rpa_stat_match(&hDbex->stat, hPattern, input, start, end);
+}
+
+
+int rpa_dbex_parse(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern, const char *input, const char *start, const char *end)
+{
+    if (!hDbex)
+        return -1;
+    if (!hPattern || !input || !start || !end) {
+        hDbex->lastError = RPA_E_INVALID_PARAM;
+        return -1;
+    }
+
+       return rpa_stat_parse(&hDbex->stat, hPattern, input, start, end);
+}
+
+
+int rpa_dbex_set_encoding(rpa_dbex_handle hDbex, unsigned int encoding)
+{
+    if (!hDbex)
+               return -1;
+    rpa_stat_set_encoding(&hDbex->stat, encoding);
+    return 0;
+}
+
+
+int rpa_dbex_get_usedstack(rpa_dbex_handle hDbex)
+{
+    if (!hDbex)
+        return -1;
+    return rpa_stat_get_usedstack(&hDbex->stat);
+}
+
+
+int rpa_dbex_reset_usedstack(rpa_dbex_handle hDbex)
+{
+    if (!hDbex)
+        return -1;
+    return rpa_stat_reset_usedstack(&hDbex->stat);
+}
+
+
+int rpa_dbex_set_progress_callback(rpa_dbex_handle hDbex, rpa_progress_callback progress, void *userdata)
+{
+    if (!hDbex)
+        return -1;
+    return rpa_stat_set_progress_callback(&hDbex->stat, progress, userdata);
+}
+
+
+int rpa_dbex_abort(rpa_dbex_handle hDbex)
+{
+    if (!hDbex)
+        return -1;
+       return rpa_stat_abort(&hDbex->stat);
+}
+
+
+int rpa_dbex_dump_pattern(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern)
+{
+    if (!hDbex)
+        return -1;
+       rpa_dump_pattern_tree(hPattern);
+       return 0;
+}
+
+
+void *rpa_dbex_get_userdata(rpa_dbex_handle hDbex, unsigned int index)
+{
+    if (!hDbex)
+        return 0;
+       return rpa_stat_get_userdata(&hDbex->stat, index);
+}
+
+
+int rpa_dbex_set_userdata(rpa_dbex_handle hDbex, unsigned int index, void *ud)
+{
+    if (!hDbex)
+        return -1;
+       return rpa_stat_set_userdata(&hDbex->stat, index, ud);
+}
+
+
+const char *rpa_dbex_version()
+{
+       return RPA_VERSION_STRING;
+}
+
+
+const char *rpa_dbex_seversion()
+{
+       return rpa_dbex_search_version();
+}
diff --git a/rpa/rpadbex.h b/rpa/rpadbex.h
new file mode 100644 (file)
index 0000000..b3b3609
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPADBEX_H_
+#define _RPADBEX_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RPA_ENCODING_ICASE 1
+#define RPA_ENCODING_BYTE 0
+#define RPA_ENCODING_ICASE_BYTE (RPA_ENCODING_BYTE | RPA_ENCODING_ICASE)
+#define RPA_ENCODING_UTF8 2
+#define RPA_ENCODING_ICASE_UTF8 (RPA_ENCODING_UTF8 | RPA_ENCODING_ICASE)
+#define RPA_ENCODING_UTF16LE 4
+#define RPA_ENCODING_ICASE_UTF16LE (RPA_ENCODING_UTF16LE | RPA_ENCODING_ICASE)
+
+#define RPA_PATTERN_SINGLE 0
+#define RPA_PATTERN_BEST 1
+#define RPA_PATTERN_OR 2
+
+
+/* 
+ * Callback reasons, the callback will set the reason for the callback
+ * RPA_REASON_END and RPA_REASON_MATCHED can be combined and delivered
+ * in the same call, if there is a match.
+ */
+#define RPA_REASON_START       (1 << 5)
+#define RPA_REASON_END         (1 << 6)
+#define RPA_REASON_MATCHED     (1 << 7)
+#define RPA_REASON_ALL         (RPA_REASON_START|RPA_REASON_END|RPA_REASON_MATCHED)
+
+
+typedef struct rpa_stat_s *rpa_stat_handle;
+typedef struct rpa_dbex_s *rpa_dbex_handle;
+typedef struct rpa_varlink_s *rpa_group_handle;
+typedef struct rpa_varlink_s *rpa_pattern_handle;
+typedef struct rpa_varlink_s *rpa_callback_handle;
+typedef void (*rpa_progress_callback)(void *userdata, const char *input, const char *start, const char *end);
+typedef int (*rpa_match_callback)(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end);
+
+
+rpa_dbex_handle rpa_dbex_create(void);
+rpa_dbex_handle rpa_dbex_create_with_hash(unsigned int uHashEntries);
+void rpa_dbex_destroy(rpa_dbex_handle hDbex);
+unsigned int rpa_dbex_get_error(rpa_dbex_handle hDbex);
+int rpa_dbex_add_callback(rpa_dbex_handle hDbex, const char *namematch, unsigned int reason, rpa_match_callback func, void *userdata);
+int rpa_dbex_open(rpa_dbex_handle hDbex);
+void rpa_dbex_close(rpa_dbex_handle hDbex);
+int rpa_dbex_load(rpa_dbex_handle hDbex, const char *patterns, unsigned int size);
+int rpa_dbex_load_string(rpa_dbex_handle hDbex, const char *patterns);
+int rpa_dbex_pattern_type(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern);
+rpa_pattern_handle rpa_dbex_get_pattern(rpa_dbex_handle hDbex, const char *name);
+rpa_pattern_handle rpa_dbex_default_pattern(rpa_dbex_handle hDbex);
+rpa_pattern_handle rpa_dbex_next_pattern(rpa_dbex_handle hDbex, rpa_pattern_handle hCur);
+rpa_pattern_handle rpa_dbex_prev_pattern(rpa_dbex_handle hDbex, rpa_pattern_handle hCur);
+rpa_pattern_handle rpa_dbex_first_pattern(rpa_dbex_handle hDbex);
+rpa_pattern_handle rpa_dbex_last_pattern(rpa_dbex_handle hDbex);
+rpa_callback_handle rpa_dbex_next_callback(rpa_dbex_handle hDbex, rpa_callback_handle hCur);
+rpa_callback_handle rpa_dbex_prev_callback(rpa_dbex_handle hDbex, rpa_callback_handle hCur);
+rpa_callback_handle rpa_dbex_first_callback(rpa_dbex_handle hDbex);
+rpa_callback_handle rpa_dbex_last_callback(rpa_dbex_handle hDbex);
+const char *rpa_dbex_callback_pattern(rpa_dbex_handle hDbex, rpa_callback_handle hCallback);
+void *rpa_dbex_callback_userdata(rpa_dbex_handle hDbex, rpa_callback_handle hCallback);
+const char *rpa_dbex_pattern_name(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern);
+const char *rpa_dbex_pattern_regex(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern, int seq);
+int rpa_dbex_strmatch(const char *str, const char *patterns);
+int rpa_dbex_scan(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern, const char *input, const char *start, const char *end, const char **where);
+int rpa_dbex_match(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern, const char *input, const char *start, const char *end);
+int rpa_dbex_parse(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern, const char *input, const char *start, const char *end);
+int rpa_dbex_set_encoding(rpa_dbex_handle hDbex, unsigned int encoding);
+int rpa_dbex_get_usedstack(rpa_dbex_handle hDbex);
+int rpa_dbex_reset_usedstack(rpa_dbex_handle hDbex);
+int rpa_dbex_set_progress_callback(rpa_dbex_handle hDbex, rpa_progress_callback progress, void *userdata);
+int rpa_dbex_abort(rpa_dbex_handle hDbex);
+int rpa_dbex_dump_pattern(rpa_dbex_handle hDbex, rpa_pattern_handle hPattern);
+void *rpa_dbex_get_userdata(rpa_dbex_handle hDbex, unsigned int index);
+int rpa_dbex_set_userdata(rpa_dbex_handle hDbex, unsigned int index, void *ud);
+const char *rpa_dbex_version();
+const char *rpa_dbex_seversion();
+
+rpa_stat_handle rpa_stat_create(rpa_dbex_handle hDbex);
+void rpa_stat_destroy(rpa_stat_handle hStat);
+int rpa_stat_set_encoding(rpa_stat_handle hStat, unsigned int encoding);
+int rpa_stat_reset_usedstack(rpa_stat_handle hStat);
+int rpa_stat_get_usedstack(rpa_stat_handle hStat);
+int rpa_stat_set_maxstack(rpa_stat_handle hStat, unsigned long size);
+int rpa_stat_scan(rpa_stat_handle hStat, rpa_pattern_handle hPattern, const char *input, const char *start, const char *end, const char **where);
+int rpa_stat_match(rpa_stat_handle hStat, rpa_pattern_handle hPattern, const char *input, const char *start, const char *end);
+int rpa_stat_parse(rpa_stat_handle hStat, rpa_pattern_handle hPattern, const char *input, const char *start, const char *end);
+int rpa_stat_set_progress_callback(rpa_stat_handle hStat, rpa_progress_callback progress, void *userdata);
+int rpa_stat_abort(rpa_stat_handle hStat);
+void *rpa_stat_get_userdata(rpa_stat_handle hStat, unsigned int index);
+int rpa_stat_set_userdata(rpa_stat_handle hStat, unsigned int index, void *ud);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpa/rpadbexpriv.c b/rpa/rpadbexpriv.c
new file mode 100644 (file)
index 0000000..84adf21
--- /dev/null
@@ -0,0 +1,964 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include "rpaerror.h"
+#include "rpavarlink.h"
+#include "rpadbexpriv.h"
+#include "rpamatch.h"
+#include "rpamnode.h"
+#include "rpastring.h"
+#include "rpamem.h"
+#include "rpamatch.h"
+#include "rpamatchspecial.h"
+#include "rpamatchstr.h"
+#include "rpamatchrange.h"
+#include "rpamatchval.h"
+#include "rpamatchlist.h"
+#include "rpamatchrangelist.h"
+#include "rpadebug.h"
+#include "rpasearch.h"
+
+#define RPA_VMSTACK_SIZE 256
+#define RPA_VMSTACK_CHUNK 64
+
+
+static rpa_word_t rpa_vmcb_create_val_matchptr(rpa_vm_t *vm);                          /* VM_CREATE_VAL_MATCHPTR 0 */
+static rpa_word_t rpa_vmcb_create_list_matchptr(rpa_vm_t *vm);                         /* VM_CREATE_LIST_MATCHPTR 1 */
+static rpa_word_t rpa_vmcb_create_nlist_matchptr(rpa_vm_t *vm);                                /* VM_CREATE_NLIST_MATCHPTR 2 */
+static rpa_word_t rpa_vmcb_get_nlist_matchptr(rpa_vm_t *vm);                           /* VM_GET_NLIST_MATCHPTR 3 */
+static rpa_word_t rpa_vmcb_create_newline_matchptr(rpa_vm_t *vm);                      /* VM_CREATE_NEWLINE_MATCHPTR 4 */
+static rpa_word_t rpa_vmcb_create_anychar_matchptr(rpa_vm_t *vm);                      /* VM_CREATE_ANYCHAR_MATCHPTR 5 */
+static rpa_word_t rpa_vmcb_create_str_matchptr(rpa_vm_t *vm);                          /* VM_CREATE_STR_MATCHPTR 6 */
+static rpa_word_t rpa_vmcb_create_range_matchptr(rpa_vm_t *vm);                                /* VM_CREATE_RANGE_MATCHPTR 7 */
+static rpa_word_t rpa_vmcb_create_mnode(rpa_vm_t *vm);                                         /* VM_CREATE_MNODE 8 */
+static rpa_word_t rpa_vmcb_create_mnode_callback(rpa_vm_t *vm);                                /* VM_CREATE_MNODE_CALLBACK 9 */
+static rpa_word_t rpa_vmcb_varlink_ptr(rpa_vm_t *vm);                                          /* VM_VARLINK_PTR 10 */
+static rpa_word_t rpa_vmcb_add_mnode_to_list(rpa_vm_t *vm);                                    /* VM_ADD_MNODE_TO_LIST 11 */
+static rpa_word_t rpa_vmcb_set_match_function(rpa_vm_t *vm);                           /* VM_SET_MATCH_FUNCTION 12 */
+static rpa_word_t rpa_vmcb_dump_tree(rpa_vm_t *vm);                                                    /* VM_DUMP_TREE 13 */
+static rpa_word_t rpa_vmcb_set_match_name(rpa_vm_t *vm);                                       /* VM_SET_MATCH_NAME 14 */
+static rpa_word_t rpa_vmcb_set_default_pattern(rpa_vm_t *vm);                          /* VM_SET_DEFAULT_PATTERN 15 */
+static rpa_word_t rpa_vmcb_setup_list(rpa_vm_t *vm);                                           /* VM_SETUP_LIST 16 */
+static rpa_word_t rpa_vcmb_add_match_to_dataptr(rpa_vm_t *vm);                         /* VM_ADD_MATCH_TO_DATAPTR 17 */
+static rpa_word_t rpa_vmcb_create_hlist_matchptr(rpa_vm_t *vm);                                /* VM_CREATE_HLIST_MATCHPTR 18 */
+static rpa_word_t rpa_vmcb_create_funlast_matchptr(rpa_vm_t *vm);                      /* VM_CREATE_FUNLAST_MATCHPTR 19 */
+static rpa_word_t rpa_vmcb_create_funabort_matchptr(rpa_vm_t *vm);                     /* VM_CREATE_FUNABORT_MATCHPTR 20 */
+static rpa_word_t rpa_vmcb_create_funfail_matchptr(rpa_vm_t *vm);                      /* VM_CREATE_FUNFAIL_MATCHPTR 21*/
+static rpa_word_t rpa_vmcb_set_strval(rpa_vm_t *vm);                                           /* VM_SET_STRVAL 22*/
+static rpa_word_t rpa_vmcb_noop(rpa_vm_t *vm);                                                         /* VM_NOOP 23*/
+static rpa_word_t rpa_vmcb_add_mnode_to_list_dataptr(rpa_vm_t *vm);            /* VM_ADD_MNODE_TO_NLIST_DATAPTR 24 */
+static rpa_word_t rpa_vmcb_get_match_function(rpa_vm_t *vm);                           /* VM_GET_MATCH_FUNCTION 25 */
+static rpa_word_t rpa_vmcb_reset_list(rpa_vm_t *vm);                                           /* VM_RESET_LIST 26 */
+static rpa_word_t rpa_vmcb_create_ragnelist_matchptr(rpa_vm_t *vm);                    /* VM_CREATE_RANGELIST_MATCHPTR 27 */
+
+
+
+static rpa_vm_callback calltable[] = {
+       rpa_vmcb_create_val_matchptr,                           /* VM_CREATE_VAL_MATCHPTR 0 */
+       rpa_vmcb_create_list_matchptr,                          /* VM_CREATE_LIST_MATCHPTR 1 */
+       rpa_vmcb_create_nlist_matchptr,                         /* VM_CREATE_NLIST_MATCHPTR 2 */
+       rpa_vmcb_get_nlist_matchptr,                            /* VM_GET_NLIST_MATCHPTR 3 */
+       rpa_vmcb_create_newline_matchptr,                       /* VM_CREATE_NEWLINE_MATCHPTR 4 */
+       rpa_vmcb_create_anychar_matchptr,                       /* VM_CREATE_ANYCHAR_MATCHPTR 5 */
+       rpa_vmcb_create_str_matchptr,                           /* VM_CREATE_STR_MATCHPTR 6 */
+       rpa_vmcb_create_range_matchptr,                         /* VM_CREATE_RANGE_MATCHPTR 7 */
+       rpa_vmcb_create_mnode,                                          /* VM_CREATE_MNODE 8 */
+       rpa_vmcb_create_mnode_callback,                         /* VM_CREATE_MNODE_CALLBACK 9 */
+       rpa_vmcb_varlink_ptr,                                           /* VM_VARLINK_PTR 10 */
+       rpa_vmcb_add_mnode_to_list,                                     /* VM_ADD_MNODE_TO_LIST 11 */
+       rpa_vmcb_set_match_function,                            /* VM_SET_MATCH_FUNCTION 12 */
+       rpa_vmcb_dump_tree,                                                     /* VM_DUMP_TREE 13 */
+       rpa_vmcb_set_match_name,                                        /* VM_SET_MATCH_NAME 14 */
+       rpa_vmcb_set_default_pattern,                           /* VM_SET_DEFAULT_PATTERN 15 */
+       rpa_vmcb_setup_list,                                            /* VM_SETUP_LIST 16 */
+       rpa_vcmb_add_match_to_dataptr,                          /* VM_ADD_MATCH_TO_DATAPTR 17 */        
+       rpa_vmcb_create_hlist_matchptr,                         /* VM_CREATE_HLIST_MATCHPTR 18 */
+       rpa_vmcb_create_funlast_matchptr,                       /* VM_CREATE_FUNLAST_MATCHPTR 19 */
+       rpa_vmcb_create_funabort_matchptr,                      /* VM_CREATE_FUNABORT_MATCHPTR 20 */
+       rpa_vmcb_create_funfail_matchptr,                       /* VM_CREATE_FUNFAIL_MATCHPTR 21 */
+       rpa_vmcb_set_strval,                                            /* VM_SET_STRVAL 22 */
+       rpa_vmcb_noop,                                                          /* VM_NOOP_23 23 */
+       rpa_vmcb_add_mnode_to_list_dataptr,                     /* VM_ADD_MNODE_TO_LIST_DATAPTR 24 */
+       rpa_vmcb_get_match_function,                            /* VM_GET_MATCH_FUNCTION 25 */
+       rpa_vmcb_reset_list,                                            /* VM_RESET_LIST 26 */
+       rpa_vmcb_create_ragnelist_matchptr,                     /* VM_CREATE_RANGELIST_MATCHPTR 27 */
+       NULL,
+};
+
+
+int rpa_common_callback(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_varlink_t *pVarLinkCallback;
+       rpa_callbackdata_t *pCbData;
+       
+       if (!(mnode->flags & RPA_MNODE_CALLBACK))
+               goto error;
+       pVarLinkCallback = (rpa_varlink_t *)((rpa_mnode_callback_t*)mnode)->userdata;
+       if (!pVarLinkCallback || pVarLinkCallback->var.userdata4 != MATCH_CLASS_CALLBACKPTR)
+               goto error;
+       pCbData = pVarLinkCallback->var.v.ptr;
+       if  (pCbData->func)
+               return pCbData->func(mnode->match->name, pCbData->userdata, input, size, reason, stat->start, stat->end);
+error:
+       return size;
+}
+
+
+void rpa_mnode_connect_callback_dontuse(rpa_dbex_handle hDbex, rpa_mnode_t *mnode)
+{
+       int ret = 0;
+       rpa_varlink_t *pCallback;
+       const char *name = (void*)0;
+       int size = name ? rpa_strlen(name) : 0;
+
+       if (!mnode || (mnode->flags & RPA_MNODE_NOCONNECT) || !mnode->match || !mnode->match->name)
+               return;
+       name = mnode->match->name;
+       size = mnode->match->namesiz;
+       for (pCallback = rpa_dbex_prev_callback(hDbex, 0); pCallback; pCallback = rpa_dbex_prev_callback(hDbex, pCallback)) {
+               rpa_callbackdata_t *pCbData = (rpa_callbackdata_t *)pCallback->var.v.ptr;
+               ret = rpa_dbex_strmatch(name, pCbData->namematch);
+               if (size && ret == size) {
+                       if (mnode->flags & RPA_MNODE_CALLBACK) {
+                               mnode->flags |= pCbData->reason;
+                               ((rpa_mnode_callback_t*)mnode)->matched_callback = rpa_common_callback;
+                               ((rpa_mnode_callback_t*)mnode)->userdata = pCallback;
+                       }
+                       return;
+               }
+       }       
+
+
+}
+
+
+void rpa_dbex_connect_callbacks(rpa_dbex_handle hDbex)
+{
+       rpa_dbex_t strdbex;
+       rpa_pattern_handle hDefault;
+       rpa_mnode_callback_t *cbmnode;
+       rpa_list_t *pos;
+       int ret;
+       rpa_varlink_t *pCallback;
+       const char *name;
+       int namelen;
+
+       for (pCallback = rpa_dbex_next_callback(hDbex, 0); pCallback; pCallback = rpa_dbex_next_callback(hDbex, pCallback)) {
+               rpa_callbackdata_t *pCbData = (rpa_callbackdata_t *)pCallback->var.v.ptr;
+               rpa_dbex_init(&strdbex, 16);
+               rpa_dbex_open(&strdbex);
+               if (rpa_dbex_load_string(&strdbex, pCbData->namematch) < 0) {
+                       rpa_dbex_cleanup(&strdbex);
+                       continue;
+               }
+               rpa_dbex_close_do(&strdbex);
+               hDefault = rpa_dbex_default_pattern(&strdbex);
+               rpa_list_for_each(pos, &hDbex->callbackmnodes) {
+                               cbmnode = rpa_list_entry(pos, rpa_mnode_callback_t, cblink);
+                       if (!cbmnode->matched_callback) {
+                               name = ((rpa_mnode_t*)cbmnode)->match->name;
+                               namelen = ((rpa_mnode_t*)cbmnode)->match->namesiz;
+                               ret = rpa_stat_match_lite(&strdbex.stat, hDefault, name, name, name + namelen);
+                               if (namelen && ret == namelen) {
+                                       ((rpa_mnode_t*)cbmnode)->flags |= pCbData->reason;
+                                       cbmnode->matched_callback = rpa_common_callback;
+                                       cbmnode->userdata = pCallback;
+                               }
+                       }
+               }
+               rpa_dbex_cleanup(&strdbex);
+       }       
+}
+
+
+
+rpa_word_t rpa_sdbm_hash(rpa_dbex_handle hDbex, const char *str)
+{
+       rpa_word_t hash = 0;
+       int c;
+
+       while ((c = *str++))
+               hash = c + (hash << 6) + (hash << 16) - hash;
+       return hash & (hDbex->namehashEntries - 1);
+}
+
+
+rpa_word_t rpa_sdbm_hash_strlen(rpa_dbex_handle hDbex, const char *str, unsigned int strlen)
+{
+       rpa_word_t hash = 0;
+       int c;
+
+       while (strlen--) {
+               c = *str++;
+               hash = c + (hash << 6) + (hash << 16) - hash;
+       }
+       return hash & (hDbex->namehashEntries - 1);
+}
+
+
+rpa_varlink_t *rpa_varlink_find_named_matchptr(rpa_head_t *head, const char *name, unsigned int size)
+{
+       rpa_list_t *pos;
+       rpa_varlink_t *pVarLinkMatch;
+
+       for (pos = rpa_list_last(head); pos; pos = rpa_list_prev(head, pos)) {
+               pVarLinkMatch = rpa_list_entry(pos, rpa_varlink_t, hlnk);
+               if (pVarLinkMatch->var.userdata4 == MATCH_CLASS_NAMEDMATCHPTR) {
+                       rpa_match_t *match = (rpa_match_t *)pVarLinkMatch->var.v.ptr;
+                       if (rpa_strncmp(match->name, name, size) == 0)
+                               return pVarLinkMatch;
+               }
+       }
+       return ((void*)0);
+}
+
+
+int rpa_dbex_check_parser(rpa_dbex_handle hDbex)
+{
+       if (!hDbex->parser)
+               hDbex->parser = rpa_parser_create();
+               
+       if (!hDbex->parser) {
+               /*
+                * Error
+                */
+               return -1;
+       }
+       return 0;
+}
+
+
+int rpa_dbex_check_vm(rpa_dbex_handle hDbex)
+{
+       int table;
+       if (!hDbex->vm)
+               hDbex->vm = rpa_vm_create();
+       if (!hDbex->vm) {
+               /*
+                * Error
+                */
+               return -1;
+       }
+       table = rpa_vm_cbtable_add(hDbex->vm, calltable);
+       /* This has to be the first(and only) call table */
+       if (table != 0)
+               return -1;
+       hDbex->vm->userdata = (void*)hDbex;
+       return 0;
+       
+}
+
+
+/*
+ * noop
+ */
+static rpa_word_t rpa_vmcb_noop(rpa_vm_t *vm)
+{
+       return vm->r[0];
+}
+
+
+/*
+ * r[0] - varlink match ptr
+ */
+static rpa_word_t rpa_vmcb_dump_tree(rpa_vm_t *vm)
+{
+       rpa_dump_pattern_tree((rpa_varlink_t*)vm->r[0]);
+       return 0;
+}
+
+
+/*
+ * r[0] - varlink match ptr
+ */
+static rpa_word_t rpa_vmcb_set_default_pattern(rpa_vm_t *vm)
+{
+       rpa_dbex_handle hDbex = (rpa_dbex_handle)vm->userdata;
+       
+       hDbex->defaultPattern = (rpa_varlink_t*)vm->r[0];
+       return 0;
+}
+
+
+rpa_varlink_t *rpa_dbex_create_dataptr(rpa_dbex_handle hDbex, void *dataptr)
+{
+       rpa_varlink_t *pVarLinkDataPtr;
+
+       pVarLinkDataPtr = rpa_varlink_create(RPA_VAR_PTR, "DATA");
+       if (!pVarLinkDataPtr)
+               return (void*)0;
+       pVarLinkDataPtr->var.v.ptr = dataptr;
+       pVarLinkDataPtr->var.userdata4 = (rpa_word_t)MATCH_CLASS_DATAPTR;
+       pVarLinkDataPtr->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkDataPtr->lnk);
+       return pVarLinkDataPtr;
+}
+
+
+rpa_varlink_t *rpa_dbex_create_mnode(rpa_dbex_handle hDbex, rpa_match_t *match, unsigned int flags)
+{
+       rpa_varlink_t *pVarLinkMnodePtr;
+
+       pVarLinkMnodePtr = rpa_varlink_create(RPA_VAR_PTR, "MNODE");
+       if (!pVarLinkMnodePtr)
+               return (void*)0;
+       if ((pVarLinkMnodePtr->var.v.ptr = (void*) rpa_mnode_create(match, flags)) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkMnodePtr);
+               return (void*)0;
+       }
+       pVarLinkMnodePtr->var.userdata4 = (rpa_word_t)MATCH_CLASS_MNODEPTR;
+       pVarLinkMnodePtr->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkMnodePtr->lnk);
+       return pVarLinkMnodePtr;
+}
+
+/*
+ * r[0] - match
+ * r[1] - flags
+ */
+static rpa_word_t rpa_vmcb_create_mnode(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_create_mnode(
+               (rpa_dbex_handle)vm->userdata,
+               (rpa_match_t*)((rpa_varlink_t*)vm->r[0])->var.v.ptr,
+               (unsigned int) vm->r[1]);
+}
+
+
+/*
+ * r[0] - hlist
+ * r[1] - match
+ */
+static rpa_word_t rpa_vcmb_add_match_to_dataptr(rpa_vm_t *vm)
+{
+       return 0;
+}
+
+
+/*
+ * r[0] - nlist
+ * r[1] - mnode
+ */
+static rpa_word_t rpa_vmcb_add_mnode_to_list_dataptr(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_add_mnode_to_list_dataptr(
+               (rpa_dbex_handle)vm->userdata,
+               (rpa_match_t*)((rpa_varlink_t*)vm->r[0])->var.v.ptr,
+               (rpa_mnode_t*)((rpa_varlink_t*)vm->r[1])->var.v.ptr);
+       return vm->r[0];
+}
+
+
+/*
+ * r[0] - match
+ */
+static rpa_word_t rpa_vmcb_get_match_function(rpa_vm_t *vm)
+{
+       rpa_match_t *match = (rpa_match_t*)((rpa_varlink_t*)vm->r[0])->var.v.ptr;
+       
+       return (rpa_word_t) match->match_function_id;
+}
+
+
+/*
+ * r[0] - list
+ */
+static rpa_word_t rpa_vmcb_reset_list(rpa_vm_t *vm)
+{
+       rpa_match_list_t *matchlist = (rpa_match_list_t*)((rpa_varlink_t*)vm->r[0])->var.v.ptr;
+       
+       rpa_list_init(&matchlist->head);
+       rpa_dbex_reset_list_dataptr((rpa_dbex_handle)vm->userdata, (rpa_match_t*)matchlist);
+       return 0;
+}
+
+
+rpa_varlink_t *rpa_dbex_create_mnode_callback(rpa_dbex_handle hDbex, rpa_match_t *match, unsigned int flags)
+{
+       rpa_varlink_t *pVarLinkMnodePtr;
+       rpa_mnode_callback_t *pCbMnode;
+
+
+       pVarLinkMnodePtr = rpa_varlink_create(RPA_VAR_PTR, "MNODECB");
+       if (!pVarLinkMnodePtr)
+               return (void*)0;
+       pCbMnode = (rpa_mnode_callback_t *)rpa_mnode_callback_create(match, flags, 0, 0);
+       if ((pVarLinkMnodePtr->var.v.ptr = (void*) pCbMnode) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkMnodePtr);
+               return (void*)0;
+       }
+       pVarLinkMnodePtr->var.userdata4 = (rpa_word_t)MATCH_CLASS_MNODEPTR;
+       pVarLinkMnodePtr->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkMnodePtr->lnk);
+       if ((((rpa_mnode_t *)pCbMnode)->flags & RPA_MNODE_NOCONNECT) == 0)
+               rpa_list_addt(&hDbex->callbackmnodes, &pCbMnode->cblink);
+       return pVarLinkMnodePtr;
+}
+
+/*
+ * r[0] match 
+ * r[1] flags
+ */
+
+static rpa_word_t rpa_vmcb_create_mnode_callback(rpa_vm_t *vm)
+{
+       
+       return (rpa_word_t)rpa_dbex_create_mnode_callback(
+               (rpa_dbex_handle)vm->userdata,
+               (rpa_match_t*)((rpa_varlink_t*)vm->r[0])->var.v.ptr,
+               (unsigned int) vm->r[1]);
+}
+
+
+static rpa_varlink_t *rpa_dbex_create_val_matchptr(rpa_dbex_handle hDbex, const char *name, unsigned int size, rpa_word_t val)
+{
+       rpa_varlink_t *pVarLinkMatchPtr;
+
+       pVarLinkMatchPtr = rpa_varlink_create(RPA_VAR_PTR, "VAL");
+       if (!pVarLinkMatchPtr) 
+               return (void*)0;
+       if ((pVarLinkMatchPtr->var.v.ptr = (void*) rpa_match_val_create_namesize(name, size, RPA_MATCHFUNC_VAL_CHREQ, (unsigned int)val)) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkMatchPtr);
+               return (void*)0;
+       }
+       pVarLinkMatchPtr->var.userdata4 = (rpa_word_t)MATCH_CLASS_MATCHPTR;
+       pVarLinkMatchPtr->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkMatchPtr->lnk);
+       return pVarLinkMatchPtr;
+}
+
+
+int rpa_dbex_int_ascii_matchptr_array(rpa_dbex_handle hDbex)
+{
+       int i;
+       
+       for (i = 0; i < RPA_PREALLOC_VAL_COUNT; i++) {
+               if ((hDbex->pVarLinkValMatchPtr[i] = rpa_dbex_create_val_matchptr(hDbex, 0, 0, i)) == (void*)0)
+                       return -1;
+       }
+       return 0;
+}
+
+/*
+ * r[0] match (varlink)
+ * r[1] name
+ * r[2] namesize
+ */
+static rpa_word_t rpa_vmcb_set_match_name(rpa_vm_t *vm)
+{
+       rpa_varlink_t *pVarLink = (rpa_varlink_t*) vm->r[0];
+       
+       rpa_match_setup_name((rpa_match_t*)pVarLink->var.v.ptr, (const char*)vm->r[1], (unsigned int)vm->r[2]);
+       return 0;
+}
+
+
+/*
+ * r[0] name
+ * r[1] namesize
+ * r[2] vale
+ */
+static rpa_word_t rpa_vmcb_create_val_matchptr(rpa_vm_t *vm)
+{
+       if ((rpa_word_t) vm->r[2] < RPA_PREALLOC_VAL_COUNT)
+               return (rpa_word_t)((rpa_dbex_handle)vm->userdata)->pVarLinkValMatchPtr[(rpa_word_t) vm->r[2]];
+
+       return (rpa_word_t)rpa_dbex_create_val_matchptr(
+               (rpa_dbex_handle)vm->userdata,
+               (const char*) vm->r[0],
+               (unsigned int) vm->r[1],
+               (rpa_word_t) vm->r[2]);
+}
+
+
+rpa_varlink_t *rpa_dbex_create_list_matchptr(rpa_dbex_handle hDbex, const char *name, unsigned int size, rpa_matchfunc_t match_function_id)
+{
+       rpa_varlink_t *pVarLinkListMatchPtr;
+
+       pVarLinkListMatchPtr = rpa_varlink_create(RPA_VAR_PTR, "LIST");
+       if (!pVarLinkListMatchPtr) 
+               return (void*)0;
+       if ((pVarLinkListMatchPtr->var.v.ptr = (void*) rpa_match_list_create_namesize(name, size, match_function_id)) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkListMatchPtr);
+               return (void*)0;
+       }
+       pVarLinkListMatchPtr->var.userdata4 = (rpa_word_t)MATCH_CLASS_MATCHPTR;
+       pVarLinkListMatchPtr->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkListMatchPtr->lnk);
+       return pVarLinkListMatchPtr;
+}
+
+
+/*
+ * r[0] name
+ * r[1] namesize
+ * r[2] list match func
+ */
+static rpa_word_t rpa_vmcb_create_list_matchptr(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_create_list_matchptr(
+               (rpa_dbex_handle)vm->userdata,
+               (const char*) vm->r[0],
+               (unsigned int) vm->r[1],
+               vm->r[2]);
+}
+
+
+rpa_varlink_t *rpa_dbex_create_rangelist_matchptr(rpa_dbex_handle hDbex, const char *name, unsigned int size)
+{
+       rpa_varlink_t *pVarLinkListMatchPtr;
+
+       pVarLinkListMatchPtr = rpa_varlink_create(RPA_VAR_PTR, "LIST");
+       if (!pVarLinkListMatchPtr) 
+               return (void*)0;
+       if ((pVarLinkListMatchPtr->var.v.ptr = (void*) rpa_match_rangelist_create_namesize(name, size, RPA_MATCHFUNC_LIST_ALT)) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkListMatchPtr);
+               return (void*)0;
+       }
+       pVarLinkListMatchPtr->var.userdata4 = (rpa_word_t)MATCH_CLASS_MATCHPTR;
+       pVarLinkListMatchPtr->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkListMatchPtr->lnk);
+       return pVarLinkListMatchPtr;
+}
+
+/*
+ * r[0] name
+ * r[1] namesize
+ */
+static rpa_word_t rpa_vmcb_create_ragnelist_matchptr(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_create_rangelist_matchptr(
+               (rpa_dbex_handle)vm->userdata,
+               (const char*) vm->r[0],
+               (unsigned int) vm->r[1]);
+}
+
+
+rpa_varlink_t *rpa_dbex_create_nlist_matchptr(rpa_dbex_handle hDbex, const char *name, unsigned int size, rpa_matchfunc_t match_function_id)
+{
+       rpa_varlink_t *pVarLinkListMatchPtr;
+
+       pVarLinkListMatchPtr = rpa_varlink_create(RPA_VAR_PTR, "NLIST");
+       if (!pVarLinkListMatchPtr)
+               return (void*)0;
+       if ((pVarLinkListMatchPtr->var.v.ptr = (void*) rpa_match_nlist_create_namesize(name, size, match_function_id)) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkListMatchPtr);
+               return (void*)0;
+       }
+       pVarLinkListMatchPtr->var.userdata4 = (rpa_word_t)MATCH_CLASS_NAMEDMATCHPTR;
+       pVarLinkListMatchPtr->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkListMatchPtr->lnk);
+       return pVarLinkListMatchPtr;
+}
+
+
+static rpa_word_t rpa_vmcb_create_nlist_matchptr(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_create_nlist_matchptr(
+               (rpa_dbex_handle)vm->userdata,
+               (const char*) vm->r[0],
+               (unsigned int) vm->r[1],
+               vm->r[2]);
+}
+
+
+rpa_varlink_t *rpa_dbex_create_hlist_matchptr(rpa_dbex_handle hDbex, const char *name, unsigned int size, rpa_matchfunc_t match_function_id)
+{
+       rpa_varlink_t *pVarLinkListMatchPtr;
+
+       pVarLinkListMatchPtr = rpa_varlink_create(RPA_VAR_PTR, "HLIST");
+       if (!pVarLinkListMatchPtr)
+               return (void*)0;
+       if ((pVarLinkListMatchPtr->var.v.ptr = (void*) rpa_match_list_create_namesize(name, size, match_function_id)) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkListMatchPtr);
+               return (void*)0;
+       }
+       pVarLinkListMatchPtr->var.userdata4 = (rpa_word_t)MATCH_CLASS_MATCHPTR;
+       pVarLinkListMatchPtr->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkListMatchPtr->lnk);
+       return pVarLinkListMatchPtr;
+}
+
+
+static rpa_word_t rpa_vmcb_create_hlist_matchptr(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_create_hlist_matchptr(
+               (rpa_dbex_handle)vm->userdata,
+               (const char*) vm->r[0],
+               (unsigned int) vm->r[1],
+               vm->r[2]);
+}
+
+
+rpa_match_t *rpa_varlink_matchptr(rpa_varlink_t *pVarLink)
+{
+       if (pVarLink) {
+               return (rpa_match_t*) pVarLink->var.v.ptr;
+       }
+       return (void*)0;
+}
+
+
+rpa_mnode_t *rpa_varlink_mnodeptr(rpa_varlink_t *pVarLink)
+{
+       if (pVarLink) {
+               return (rpa_mnode_t*) pVarLink->var.v.ptr;
+       }
+       return (void*)0;
+}
+
+
+static rpa_word_t rpa_vmcb_varlink_ptr(rpa_vm_t *vm)
+{
+       rpa_varlink_t *pVarLink = (rpa_varlink_t*)vm->r[0];
+
+       return (rpa_word_t) pVarLink->var.v.ptr;
+}
+
+
+/*
+ * r[0] - varlink
+ * r[1] - match function id
+ */
+static rpa_word_t rpa_vmcb_set_match_function(rpa_vm_t *vm)
+{
+       rpa_varlink_t *pVarLink = (rpa_varlink_t*)vm->r[0];
+
+       rpa_match_set_mathfunc((rpa_match_t*) pVarLink->var.v.ptr, vm->r[1]);
+       return (rpa_word_t) 0;
+}
+
+
+rpa_varlink_t *rpa_dbex_get_nlist_matchptr(rpa_dbex_handle hDbex, const char *name, unsigned int size)
+{
+       rpa_varlink_t *pVarLinkListMatchPtr = 0;
+       rpa_head_t *bucket;
+       
+       bucket = &hDbex->namehash[rpa_sdbm_hash_strlen(hDbex, name, size)];
+       pVarLinkListMatchPtr = rpa_varlink_find_named_matchptr(bucket, name, size);
+       if (!pVarLinkListMatchPtr) {
+               pVarLinkListMatchPtr = rpa_dbex_create_nlist_matchptr(hDbex, name, size, RPA_MATCHFUNC_LIST);
+               if (pVarLinkListMatchPtr)
+                       rpa_list_addt(bucket, &pVarLinkListMatchPtr->hlnk);
+       }
+
+       return pVarLinkListMatchPtr;
+}
+
+
+/*
+ * r[0] - name
+ * r[1] - name size
+ * 
+ * return hlist matchptr (varlink)
+ */
+static rpa_word_t rpa_vmcb_get_nlist_matchptr(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_get_nlist_matchptr(
+               (rpa_dbex_handle)vm->userdata,
+               (const char*) vm->r[0],
+               (unsigned int) vm->r[1]);
+}
+
+
+rpa_varlink_t *rpa_dbex_create_newline_matchptr(rpa_dbex_handle hDbex, const char *name, unsigned int size)
+{
+       rpa_varlink_t *pVarLinkMatch;
+
+       pVarLinkMatch = rpa_varlink_create(RPA_VAR_PTR, "NEWLINE");
+       if (!pVarLinkMatch)
+               return (void*)0;
+       if ((pVarLinkMatch->var.v.ptr = (void*) rpa_match_special_create_namesize(name, size, RPA_MATCHFUNC_NEWLINE)) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkMatch);
+               return (void*)0;
+       }
+       pVarLinkMatch->var.userdata4 = (rpa_word_t)MATCH_CLASS_MATCHPTR;
+       pVarLinkMatch->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkMatch->lnk);
+       return pVarLinkMatch;
+}
+
+
+/*
+ * r[0] - name
+ * r[1] - size
+ */
+static rpa_word_t rpa_vmcb_create_newline_matchptr(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_create_newline_matchptr(
+               (rpa_dbex_handle)vm->userdata,
+               (const char*) vm->r[0],
+               (unsigned int) vm->r[1]);       
+}
+
+
+rpa_varlink_t *rpa_dbex_create_anychar_matchptr(rpa_dbex_handle hDbex, const char *name, unsigned int size)
+{
+       rpa_varlink_t *pVarLinkMatch;
+
+       pVarLinkMatch = rpa_varlink_create(RPA_VAR_PTR, "ANYCHAR");
+       if (!pVarLinkMatch)
+               return (void*)0;        
+       if ((pVarLinkMatch->var.v.ptr = (void*) rpa_match_special_create_namesize(name, size, RPA_MATCHFUNC_CHREQANY)) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkMatch);
+               return (void*)0;                
+       }
+       pVarLinkMatch->var.userdata4 = (rpa_word_t)MATCH_CLASS_MATCHPTR;
+       pVarLinkMatch->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkMatch->lnk);
+       return pVarLinkMatch;
+}
+
+
+/*
+ * r[0] - name
+ * r[1] - size
+ */
+static rpa_word_t rpa_vmcb_create_anychar_matchptr(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_create_anychar_matchptr(
+               (rpa_dbex_handle)vm->userdata,
+               (const char*) vm->r[0],
+               (unsigned int) vm->r[1]);
+}
+
+
+rpa_varlink_t *rpa_dbex_create_str_matchptr(rpa_dbex_handle hDbex, const char *input, unsigned int size, rpa_word_t count)
+{
+       rpa_varlink_t *pVarLinkStr;
+
+       pVarLinkStr = rpa_varlink_create(RPA_VAR_PTR, "STR");
+       if (!pVarLinkStr) 
+               return (void*)0;
+       if ((pVarLinkStr->var.v.ptr = (void*) rpa_match_str_create_namesize(input, size, RPA_MATCHFUNC_STR)) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkStr);
+               return (void*)0;
+       }
+       pVarLinkStr->var.userdata4 = (rpa_word_t)MATCH_CLASS_MATCHPTR;
+       pVarLinkStr->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkStr->lnk);
+       if (!rpa_match_str_alloc_strval((rpa_match_t*)pVarLinkStr->var.v.ptr, (unsigned long)count)) {
+               /*
+                * TBD: Handle the error
+                */
+
+               
+       }
+       return pVarLinkStr;
+}
+
+/*
+ * r[0] - name
+ * r[1] - size
+ * r[2] - count
+ */
+static rpa_word_t rpa_vmcb_create_str_matchptr(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_create_str_matchptr(
+               (rpa_dbex_handle)vm->userdata,
+               (const char*) vm->r[0],
+               (unsigned int) vm->r[1],
+               vm->r[2]);
+}
+
+/*
+ * r[0] - varlink
+ * r[1] - val
+ * r[2] - offset
+ */
+static rpa_word_t rpa_vmcb_set_strval(rpa_vm_t *vm)
+{
+       rpa_varlink_t *pVarLink = (rpa_varlink_t*)vm->r[0];
+
+       rpa_match_str_setval((rpa_match_t*) pVarLink->var.v.ptr, (unsigned int)vm->r[1], vm->r[2]);
+       return (rpa_word_t) 0;
+}
+
+
+/*
+ * r[0] - varlink match ptr
+ */
+static rpa_word_t rpa_vmcb_setup_list(rpa_vm_t *vm)
+{
+       rpa_dbex_handle hDbex = (rpa_dbex_handle)vm->userdata;
+       rpa_match_t *match = (rpa_match_t*)((rpa_varlink_t*)vm->r[0])->var.v.ptr;
+       rpa_dbex_setup_list(hDbex, match);
+       return 0;
+}
+
+
+rpa_varlink_t *rpa_dbex_create_range_matchptr(rpa_dbex_handle hDbex, const char *name, unsigned int size, rpa_word_t low, rpa_word_t high)
+{
+       rpa_varlink_t *pVarLinkRange;
+       
+       if (low > high) {
+               /*
+                * Swap the values;
+                */
+               high = high ^ low;
+               low = high ^ low;
+               high = high ^ low;
+       }
+
+       pVarLinkRange = rpa_varlink_create(RPA_VAR_PTR, "RANGE");
+       if (!pVarLinkRange)
+               return (void*)0;
+       if ((pVarLinkRange->var.v.ptr = (void*) rpa_match_range_create_namesize(name, size, RPA_MATCHFUNC_RANGE_CHRINRANGE, 
+               (unsigned int)low, (unsigned int)high)) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkRange);
+               return (void*)0;
+       }
+       pVarLinkRange->var.userdata4 = (rpa_word_t)MATCH_CLASS_MATCHPTR;
+       pVarLinkRange->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkRange->lnk);
+       return pVarLinkRange;
+}
+
+
+/*
+ * r[0] - name
+ * r[1] - size
+ * r[2] - low
+ * r[3] - high
+ */
+static rpa_word_t rpa_vmcb_create_range_matchptr(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_create_range_matchptr(
+               (rpa_dbex_handle)vm->userdata,
+               (const char*) vm->r[0],
+               (unsigned int) vm->r[1],
+               (unsigned int) vm->r[2],
+               (unsigned int) vm->r[3]);
+}
+
+
+
+rpa_varlink_t *rpa_dbex_create_funlast_matchptr(rpa_dbex_handle hDbex, const char *name, unsigned int size)
+{
+       rpa_varlink_t *pVarLinkMatch;
+
+       pVarLinkMatch = rpa_varlink_create(RPA_VAR_PTR, "FUNLAST");
+       if (!pVarLinkMatch)
+               return (void*)0;
+       if ((pVarLinkMatch->var.v.ptr = (void*) rpa_match_special_create_namesize(name, size, RPA_MATCHFUNC_LSTCHR)) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkMatch);
+               return (void*)0;
+       }
+       pVarLinkMatch->var.userdata4 = (rpa_word_t)MATCH_CLASS_MATCHPTR;
+       pVarLinkMatch->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkMatch->lnk);
+       return pVarLinkMatch;
+}
+
+
+/*
+ * r[0] - name
+ * r[1] - size
+ */
+static rpa_word_t rpa_vmcb_create_funlast_matchptr(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_create_funlast_matchptr(
+               (rpa_dbex_handle)vm->userdata,
+               (const char*) vm->r[0],
+               (unsigned int) vm->r[1]);       
+}
+
+
+rpa_varlink_t *rpa_dbex_create_funabort_matchptr(rpa_dbex_handle hDbex, const char *name, unsigned int size)
+{
+       rpa_varlink_t *pVarLinkMatch;
+
+       pVarLinkMatch = rpa_varlink_create(RPA_VAR_PTR, "FUNLAST");
+       if (!pVarLinkMatch)
+               return (void*)0;
+       if ((pVarLinkMatch->var.v.ptr = (void*) rpa_match_special_create_namesize(name, size, RPA_MATCHFUNC_ABORT)) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkMatch);
+               return (void*)0;
+       }
+       pVarLinkMatch->var.userdata4 = (rpa_word_t)MATCH_CLASS_MATCHPTR;
+       pVarLinkMatch->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkMatch->lnk);
+       return pVarLinkMatch;
+}
+
+
+/*
+ * r[0] - name
+ * r[1] - size
+ */
+static rpa_word_t rpa_vmcb_create_funabort_matchptr(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_create_funabort_matchptr(
+               (rpa_dbex_handle)vm->userdata,
+               (const char*) vm->r[0],
+               (unsigned int) vm->r[1]);       
+}
+
+
+rpa_varlink_t *rpa_dbex_create_funfail_matchptr(rpa_dbex_handle hDbex, const char *name, unsigned int size)
+{
+       rpa_varlink_t *pVarLinkMatch;
+
+       pVarLinkMatch = rpa_varlink_create(RPA_VAR_PTR, "FUNFAIL");
+       if (!pVarLinkMatch)
+               return (void*)0;
+       if ((pVarLinkMatch->var.v.ptr = (void*) rpa_match_special_create_namesize(name, size, RPA_MATCHFUNC_FAIL)) == (void*)0) {
+               rpa_varlink_destroy(pVarLinkMatch);
+               return (void*)0;
+       }
+       pVarLinkMatch->var.userdata4 = (rpa_word_t)MATCH_CLASS_MATCHPTR;
+       pVarLinkMatch->var.finalize = rpa_var_class_destroy;
+       rpa_list_addt(&hDbex->treehead, &pVarLinkMatch->lnk);
+       return pVarLinkMatch;
+}
+
+
+/*
+ * r[0] - name
+ * r[1] - size
+ */
+static rpa_word_t rpa_vmcb_create_funfail_matchptr(rpa_vm_t *vm)
+{
+       return (rpa_word_t)rpa_dbex_create_funfail_matchptr(
+               (rpa_dbex_handle)vm->userdata,
+               (const char*) vm->r[0],
+               (unsigned int) vm->r[1]);       
+}
+
+
+/*
+ * r[0] - list (varlink)
+ * r[1] - mnode (varlink)
+ */
+static rpa_word_t rpa_vmcb_add_mnode_to_list(rpa_vm_t *vm)
+{
+       rpa_varlink_t *pVarLinkList = (rpa_varlink_t *) vm->r[0];
+       rpa_varlink_t *pVarLinkMnode = (rpa_varlink_t *) vm->r[1];
+       rpa_match_list_t *list = (rpa_match_list_t *)pVarLinkList->var.v.ptr;
+       rpa_mnode_t *mnode = (rpa_mnode_t *)pVarLinkMnode->var.v.ptr;
+       rpa_list_addt(&list->head, &mnode->mlink);
+       return 0;
+}
+
+
+void rpa_dbex_set_mnode_quantity(rpa_dbex_handle hDbex, rpa_mnode_t *mnode, unsigned int flags)
+{
+       mnode->flags |= flags;
+}
diff --git a/rpa/rpadbexpriv.h b/rpa/rpadbexpriv.h
new file mode 100644 (file)
index 0000000..d6f0c7e
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPADBEXPRIV_H_
+#define _RPADBEXPRIV_H_
+
+#include "rpalist.h"
+#include "rpadbex.h"
+#include "rpavarlink.h"
+#include "rpamatch.h"
+#include "rpamatchval.h"
+#include "rpastat.h"
+#include "rpaparser.h"
+#include "rpavm.h"
+#include "rpatypedef.h"
+
+#define RPA_MATCH_NEWLINE_CLASSID      (('\0' << 24) | ('n' << 16) | ('l' << 8) | ('n' << 0))
+#define RPA_MATCH_LASTCHR_CLASSID      (('\0' << 24) | ('c' << 16) | ('s' << 8) | ('l' << 0))
+#define RPA_NAMEHASH_SIZE 4096
+#define RPA_VALHASH_SIZE 128
+#define RPA_PREALLOC_VAL_COUNT 128
+
+#define VM_CREATE_VAL_MATCHPTR 0
+#define VM_CREATE_LIST_MATCHPTR 1
+#define VM_CREATE_NLIST_MATCHPTR 2
+#define VM_GET_NLIST_MATCHPTR 3
+#define VM_CREATE_NEWLINE_MATCHPTR 4
+#define VM_CREATE_ANYCHAR_MATCHPTR 5
+#define VM_CREATE_STR_MATCHPTR 6
+#define VM_CREATE_RANGE_MATCHPTR 7
+#define VM_CREATE_MNODE 8
+#define VM_CREATE_MNODE_CALLBACK 9
+#define VM_VARLINK_PTR 10
+#define VM_ADD_MNODE_TO_LIST 11
+#define VM_SET_MATCH_FUNCTION 12
+#define VM_DUMP_TREE 13
+#define VM_SET_MATCH_NAME 14
+#define VM_SET_DEFAULT_PATTERN 15
+#define VM_SETUP_LIST 16
+#define VM_ADD_MATCH_TO_DATAPTR 17
+#define VM_CREATE_HLIST_MATCHPTR 18
+#define VM_CREATE_FUNLAST_MATCHPTR 19
+#define VM_CREATE_FUNABORT_MATCHPTR 20
+#define VM_CREATE_FUNFAIL_MATCHPTR 21
+#define VM_SET_STRVAL 22
+#define VM_NOOP_23 23 
+#define VM_ADD_MNODE_TO_LIST_DATAPTR 24
+#define VM_GET_MATCH_FUNCTION 25
+#define VM_RESET_LIST 26
+#define VM_CREATE_RANGELIST_MATCHPTR 27
+
+
+struct rpa_dbex_s {
+       rpa_head_t treehead;
+       rpa_head_t *namehash;
+       unsigned int namehashEntries;
+       rpa_head_t callbacks;
+       rpa_head_t callbackmnodes;
+       rpa_stat_t stat;
+       unsigned int rwlock;
+       rpa_pattern_handle defaultPattern;
+       unsigned int lastError;
+       rpa_parser_t *parser;
+       rpa_vm_t *vm;
+       rpa_varlink_t *pVarLinkValMatchPtr[RPA_PREALLOC_VAL_COUNT];
+       void *dataptr;
+};
+
+
+typedef struct rpa_callbackdata_s {
+       unsigned int reason;
+       rpa_match_callback func;
+       void *userdata;
+       char namematch[1];
+} rpa_callbackdata_t;
+
+
+rpa_varlink_t *rpa_dbex_next_callback(rpa_dbex_handle hDbex, rpa_varlink_t *cur);
+rpa_varlink_t *rpa_dbex_prev_callback(rpa_dbex_handle hDbex, rpa_varlink_t *cur);
+int rpa_dbex_build(rpa_dbex_handle hDbex, const char *input);
+void rpa_dbex_cleanup_buildstack(rpa_dbex_handle hDbex);
+rpa_mnode_t *rpa_dbex_build_tree(rpa_dbex_handle hDbex);
+int rpa_dbex_check_parser(rpa_dbex_handle hDbex);
+int rpa_dbex_check_vm(rpa_dbex_handle hDbex);
+rpa_varlink_t *rpa_dbex_create_mnode(rpa_dbex_handle hDbex, rpa_match_t *match, unsigned int flags);
+int rpa_dbex_int_ascii_matchptr_array(rpa_dbex_handle hDbex);
+rpa_dbex_handle rpa_dbex_init(rpa_dbex_handle hDbex, unsigned int namehashEntries);
+void rpa_dbex_close_do(rpa_dbex_handle hDbex);
+void rpa_dbex_cleanup(rpa_dbex_handle hDbex);
+void rpa_dbex_connect_callbacks(rpa_dbex_handle hDbex);
+#endif
diff --git a/rpa/rpadebug.c b/rpa/rpadebug.c
new file mode 100644 (file)
index 0000000..3acb0f3
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include "rpaclass.h"
+#include "rpadbexpriv.h"
+#include "rpamatch.h"
+#include "rpastring.h"
+#include "rpamem.h"
+#include "rpamatch.h"
+#include "rpamnode.h"
+#include "rpamatchstr.h"
+#include "rpamatchrange.h"
+#include "rpamatchval.h"
+#include "rpamatchlist.h"
+#include "rpautf.h"
+#include "rpadebug.h"
+#include "rpavarlink.h"
+#include "rpasearch.h"
+
+#define PRINT_STACK_SIZE 3000
+
+
+const char *get_match_func(rpa_match_t *match)
+{
+       if (match->match_function_id == RPA_MATCHFUNC_LIST)
+               return "all";
+       else if (match->match_function_id == RPA_MATCHFUNC_LIST_ALT || match->match_function_id == RPA_MATCHFUNC_NLIST_ALT)
+               return "or";
+       else if (match->match_function_id == RPA_MATCHFUNC_NLIST_BESTALT)
+               return "best";
+       else if (match->match_function_id == RPA_MATCHFUNC_LIST_CONTAIN)
+               return "cont";
+       else if (match->match_function_id == RPA_MATCHFUNC_LIST_AND)
+               return "and";
+       else if (match->match_function_id == RPA_MATCHFUNC_LIST_MINUS)
+               return "minus";
+       else if (match->match_function_id == RPA_MATCHFUNC_LIST_NOT)
+               return "not";
+       else if (match->match_function_id == RPA_MATCHFUNC_VAL_CHREQ)
+               return "eq";
+       else if (match->match_function_id == RPA_MATCHFUNC_VAL_CHRNOTEQ)
+               return "noteq";
+       else if (match->match_function_id == RPA_MATCHFUNC_CHREQANY)
+               return "any";
+       else if (match->match_function_id == RPA_MATCHFUNC_RANGE_CHRINRANGE)
+               return "inrng";
+       else if (match->match_function_id == RPA_MATCHFUNC_RANGE_CHRNOTINRANGE)
+               return "notinrng";
+       else if (match->match_function_id == RPA_MATCHFUNC_STR)
+               return "eq";
+       else if (match->match_function_id == RPA_MATCHFUNC_STR_CHRINSTR) 
+               return "chrstr";
+       else if (match->match_function_id == RPA_MATCHFUNC_STR_CHRNOTINSTR) 
+               return "chrnstr";
+
+       return "unk";
+}
+
+
+void rpa_dump_tree(rpa_match_t *match, unsigned int flags, int level, rpa_match_t **stack, int cur, int max)
+{
+       int i;
+       char q = 'x', l = 'x';
+       
+       if (level >= max)
+               return;
+
+       if ((flags & (RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE)) == (RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE))
+               q = '*';
+       else if ((flags & RPA_MATCH_MULTIPLE) == RPA_MATCH_MULTIPLE)
+               q = '+';
+       else if ((flags & RPA_MATCH_OPTIONAL) == RPA_MATCH_OPTIONAL)
+               q = '?';
+       else
+               q = 'x';
+               
+       if ((flags & RPA_MNODE_LOOP)) {
+               l = 'l';
+       }       
+       
+       if ((rpa_class_getid((rpa_class_t*)match) & RPA_MATCH_NLIST_CLASSID) && level > 0 ) {
+               char szdataptr[4096];
+               szdataptr[0] = '\0';
+               rpa_dump_list_dataptr(match, szdataptr, sizeof(szdataptr));
+               for (i = 0; i < level; i++)
+                       rpa_printf("    ");
+               rpa_printf("(%3s, %s, %c %c) <:%s:> %s\n", rpa_class_getstr((rpa_class_t*)match), get_match_func(match), q, l, match->name, szdataptr);
+               for (i = cur; i > 0; i--) {
+                       if (stack[i] == match)
+                               return;
+               }
+               if (cur >= max)
+                       return;
+               stack[++cur] = match;
+       } else if (rpa_class_getid((rpa_class_t*)match) & RPA_MATCH_LIST_CLASSID || (rpa_class_getid((rpa_class_t*)match) & RPA_MATCH_NLIST_CLASSID && level < 1)) {
+               char szdataptr[4096];
+               rpa_mnode_t *node;
+               rpa_list_t *pos;
+               rpa_match_list_t *matchList = (rpa_match_list_t *)match;
+               szdataptr[0] = '\0';
+               rpa_dump_list_dataptr(match, szdataptr, sizeof(szdataptr));
+               for (i = 0; i < level; i++)
+                       rpa_printf("    ");
+               rpa_printf("(%3s, %s, %c %c) %s %s\n", rpa_class_getstr((rpa_class_t*)match), get_match_func(match), q, l, match->name, szdataptr);
+               for (i = cur; i > 0; i--) {
+                       if (stack[i] == match)
+                               return;
+               }
+               if (cur >= max)
+                       return;
+               stack[++cur] = match;
+               rpa_list_for_each(pos, &matchList->head) {
+                       node = rpa_list_entry(pos, rpa_mnode_t, mlink);
+                       rpa_dump_tree(node->match, node->flags, level + 1, stack, cur, max);
+               }
+       } else if (rpa_class_getid((rpa_class_t*)match) & RPA_MATCH_STR_CLASSID) {
+               for (i = 0; i < level; i++)
+                       rpa_printf("    ");
+               rpa_printf("(%3s, %s, %c) %s\n", rpa_class_getstr((rpa_class_t*)match), get_match_func(match), 
+                                               q, match->name);
+       } else if (rpa_class_getid((rpa_class_t*)match) & RPA_MATCH_VAL_CLASSID) {
+                       unsigned char mb[7];
+                       rpa_memset(mb, 0, sizeof(mb));
+                       rpa_utf8_wctomb(((rpa_match_val_t*)match)->val, mb, sizeof(mb));
+                       for (i = 0; i < level; i++)
+                               rpa_printf("    ");
+                       rpa_printf("(%3s, %s, %c) %s (0x%x)\n", rpa_class_getstr((rpa_class_t*)match), get_match_func(match), q, mb, ((rpa_match_val_t*)match)->val);
+       } else {
+               for (i = 0; i < level; i++)
+                       rpa_printf("    ");
+               rpa_printf("(%3s, %s, %c) %s\n", rpa_class_getstr((rpa_class_t*)match), get_match_func(match), q, match->name);
+       }
+}
+
+
+void rpa_dump_match_tree(rpa_match_t *match)
+{
+       rpa_match_t *printStack[PRINT_STACK_SIZE];
+       if (match)
+               rpa_dump_tree(match, 0, 0, printStack, 0, PRINT_STACK_SIZE - 1);
+}
+
+
+void rpa_dump_pattern_tree(rpa_pattern_handle pattern)
+{
+       if (pattern)
+               rpa_dump_match_tree((rpa_match_t*)pattern->var.v.ptr);
+}
+
+
+
+#ifdef DEBUG
+
+
+long rpa_get_alloc_mem()
+{
+       return g_rpa_allocmem;
+}
+
+
+long rpa_get_alloc_maxmem()
+{
+       return g_rpa_maxmem;
+}
+
+
+void rpa_varlink_dump(rpa_varlink_ptr pVarLink)
+{
+       if (pVarLink->var.userdata4 == MATCH_CLASS_NAMEDMATCHPTR && pVarLink->var.type == RPA_VAR_PTR) {
+               rpa_printf("%35s: ", "NAMEDMATCHPTR");
+               if ( rpa_class_getid((rpa_class_t*)pVarLink->var.v.ptr) & RPA_MATCH_LIST_CLASSID) {
+                       rpa_match_list_t *match = (rpa_match_list_t*)pVarLink->var.v.ptr;
+                       rpa_printf("%s (rpa_match_list_t)", match->base.name);
+               }
+       } else if (pVarLink->var.userdata4 == MATCH_CLASS_MATCHPTR && pVarLink->var.type == RPA_VAR_PTR) {
+               rpa_printf("%35s: ", "MATCHPTR");
+               if ( rpa_class_getid((rpa_class_t*)pVarLink->var.v.ptr) == RPA_MATCH_NEWLINE_CLASSID) {
+                       rpa_printf("~ (rpa_match_t)");
+               } else if ( rpa_class_getid((rpa_class_t*)pVarLink->var.v.ptr) & RPA_MATCH_VAL_CLASSID) {
+                       rpa_match_val_t *match = (rpa_match_val_t*)pVarLink->var.v.ptr;
+                       unsigned char mb[7];
+                       rpa_memset(mb, 0, sizeof(mb));
+                       rpa_utf8_wctomb(match->val, mb, sizeof(mb));
+                       rpa_printf("%s (rpa_match_val_t)", mb);
+               } else if (rpa_class_getid((rpa_class_t*)pVarLink->var.v.ptr) & RPA_MATCH_RANGE_CLASSID) {
+                       unsigned char low[7], high[7];
+                       rpa_match_range_t *match = (rpa_match_range_t*)pVarLink->var.v.ptr;
+                       rpa_memset(low, 0, sizeof(low));
+                       rpa_memset(high, 0, sizeof(high));
+                       rpa_utf8_wctomb((int)match->low, low, sizeof(low));
+                       rpa_utf8_wctomb((int)match->high, high, sizeof(high));
+                       rpa_printf("%s-%s (rpa_match_range_t)", low, high);
+               } else if (rpa_class_getid((rpa_class_t*)pVarLink->var.v.ptr) & RPA_MATCH_STR_CLASSID) {
+                       rpa_match_str_t *match = (rpa_match_str_t*)pVarLink->var.v.ptr;
+                       rpa_printf("%s (rpa_match_str_t)", match->base.name);
+               } else if (rpa_class_getid((rpa_class_t*)pVarLink->var.v.ptr) & RPA_MATCH_LIST_CLASSID) {
+                       rpa_match_list_t *match = (rpa_match_list_t*)pVarLink->var.v.ptr;
+                       rpa_printf("%s (rpa_match_list_t)", match->base.name);
+               }
+
+       } else if (pVarLink->var.userdata4 == MATCH_CLASS_MNODEPTR && pVarLink->var.type == RPA_VAR_PTR) {
+               rpa_mnode_t *mnode = (rpa_mnode_t*)pVarLink->var.v.ptr;
+               rpa_printf("%35s: ", "MNODEPTR");
+               rpa_printf("%s (rpa_mnode_t), flags = 0x%x", mnode->match->name, mnode->flags);
+       }
+
+       rpa_printf("\n");
+}
+
+
+void rpa_dump_all(rpa_head_t *head)
+{
+       rpa_list_t *pos;
+       rpa_varlink_t *pVarLink;
+
+       rpa_list_for_each(pos, head) {
+               pVarLink = rpa_list_entry(pos, rpa_varlink_t, lnk);
+               rpa_varlink_dump(pVarLink);
+       }
+}
+
+
+void rpa_dump_stack(rpa_dbex_handle hDbex)
+{
+       rpa_dump_all(&hDbex->treehead);
+}
+
+
+int rpa_mnode_debug_print(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+#ifdef DEBUGPRINT
+       rpa_mnode_print(mnode, stat, input, size, reason);
+#endif
+       return size;
+}
+
+int rpa_mnode_print(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       char *reasonstr;
+
+       if (reason & RPA_REASON_START)
+               reasonstr = " s";
+       else if ((reason & RPA_REASON_END) && (reason & RPA_REASON_MATCHED))
+               reasonstr = "me";
+       else if (reason & RPA_REASON_END)
+               reasonstr = " e";
+       else if (reason & RPA_REASON_MATCHED)
+               reasonstr = "m ";
+       else 
+               reasonstr = "no";
+
+       rpa_printf("%s (%ld, %2d) %30s: ", reasonstr, (long)(input - stat->start), size, mnode->match->name);
+       while (input && size) {
+               rpa_printf("%c", *input++);
+               size -= 1;
+               // max one char for RPA_REASON_START callbacks
+               if (reason & RPA_REASON_START) {
+                       rpa_printf(" ...");
+                       break;
+               }
+       }
+       rpa_printf("\n");
+       return size;
+}
+
+
+#else
+
+
+void rpa_dump_stack(rpa_dbex_handle hDbex)
+{
+
+
+}
+
+
+int rpa_mnode_print(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+
+{
+       return size;
+}
+
+
+int rpa_mnode_debug_print(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       return size;
+}
+
+
+#endif
diff --git a/rpa/rpadebug.h b/rpa/rpadebug.h
new file mode 100644 (file)
index 0000000..50b24d3
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#if !defined(RPADEBUG_H)
+#define RPADEBUG_H
+
+
+#include "rpadbex.h"
+
+#define RPA_BREAK __asm__ ("int $3")
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct rpa_varlink_s *rpa_varlink_ptr;
+
+void rpa_dump_pattern_tree(rpa_pattern_handle pattern);
+void rpa_dump_stack(rpa_dbex_handle hDbex);
+void rpa_varlink_dump(rpa_varlink_ptr pVarLink);
+long rpa_get_alloc_mem();
+long rpa_get_alloc_maxmem();
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpa/rpaerror.h b/rpa/rpaerror.h
new file mode 100644 (file)
index 0000000..b45f5f4
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPAERROR_H_
+#define _RPAERROR_H_
+
+#define RPA_E_NONE 0
+
+#define RPA_E_INVALID_PARAM 1001
+#define RPA_E_INVALID_PATTERN 1002
+#define RPA_E_OUTOFMEM 1003
+#define RPA_E_INVALID_INPUT 1004
+#define RPA_E_INVALID_BRACKETS 1005
+#define RPA_E_INVALID_SQUAREBRACKETS 1006
+#define RPA_E_NOTOPEN 1007
+#define RPA_E_SYNTAX_ERROR 1008
+
+#endif
diff --git a/rpa/rpalist.c b/rpa/rpalist.c
new file mode 100644 (file)
index 0000000..956f734
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include "rpalist.h"
+
+
+void rpa_list_init(rpa_list_t *ptr)
+{
+       ptr->pNext = ptr; 
+       ptr->pPrev = ptr;
+}
+
+
+void rpa_list_add(rpa_list_t *pNew, rpa_list_t *pPrev, rpa_list_t *pNext)
+{
+       pNext->pPrev = pNew;
+       pNew->pNext = pNext;
+       pNew->pPrev = pPrev;
+       pPrev->pNext = pNew;
+}
+
+
+void rpa_list_addh(rpa_list_t *pHead, rpa_list_t *pNew)
+{
+       rpa_list_add(pNew, pHead, (pHead)->pNext);
+}
+
+
+void rpa_list_addt(rpa_list_t *pHead, rpa_list_t *pNew)
+{
+       rpa_list_add(pNew, (pHead)->pPrev, pHead);
+}
+
+
+void rpa_list_unlink(rpa_list_t *pPrev, rpa_list_t *pNext)
+{
+       pNext->pPrev = pPrev;
+       pPrev->pNext = pNext;
+}
+
+
+void rpa_list_del(rpa_list_t *pEntry) 
+{
+       rpa_list_unlink((pEntry)->pPrev, (pEntry)->pNext);
+}
+
+
+rpa_list_t *rpa_list_first(rpa_list_t *pHead) 
+{
+       return (((pHead)->pNext != (pHead)) ? (pHead)->pNext: ((void*)0));
+}
+
+
+rpa_list_t *rpa_list_last(rpa_list_t *pHead)
+{
+       return (((pHead)->pPrev != (pHead)) ? (pHead)->pPrev: ((void*)0));
+}
+
+
+rpa_list_t *rpa_list_prev(rpa_list_t *pHead, rpa_list_t *pElem)
+{
+       return (pElem && pElem->pPrev != pHead) ? (pElem)->pPrev: ((void*)0);
+}
+
+
+rpa_list_t *rpa_list_next(rpa_list_t *pHead, rpa_list_t *pElem)
+{
+       return (pElem && pElem->pNext != pHead) ? pElem->pNext: ((void*)0);
+}
+
+
+void rpa_list_splice(rpa_list_t *pList, rpa_list_t *pHead)
+{
+       rpa_list_t *pFirst;
+
+       pFirst = pList->pNext;
+       if (pFirst != pList) {
+               rpa_list_t *pLast = pList->pPrev;
+               rpa_list_t *pAt = pHead->pNext;
+               pFirst->pPrev = pHead;
+               pHead->pNext = pFirst;
+               pLast->pNext = pAt;
+               pAt->pPrev = pLast;
+       }
+}
+
+
+int rpa_list_count(rpa_list_t *pHead)
+{
+       rpa_list_t *pCur;
+       int n = 0;
+
+       rpa_list_for_each(pCur, pHead)
+               n++;
+       return n;
+}
diff --git a/rpa/rpalist.h b/rpa/rpalist.h
new file mode 100644 (file)
index 0000000..bf55b7e
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#if !defined(RPALIST_H)
+#define RPALIST_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RPA_LIST_HEAD(_name) {&(_name), &(_name) }
+#define rpa_list(_name) rpa_list_t _name = { &(_name), &(_name) }
+#define rpa_list_empty(_head) ((_head)->pNext == ((void*)0) || (_head)->pNext == _head)
+#define rpa_list_entry(_ptr, _type, member) ((_type *)((char *)(_ptr)-(rpa_word_t)(&((_type *)0)->member)))
+#define rpa_list_for_each(_pos, _head) for (_pos = (_head)->pNext; _pos != (_head); _pos = (_pos)->pNext)
+#define rpa_list_for_each_reverse(_pos, _head) for (_pos = (_head)->pPrev; _pos != (_head); _pos = (_pos)->pPrev)
+#define rpa_list_for_each_SAFE(_pos, _n, _head) \
+                 for (_pos = (_head)->pNext, _n = _pos->pNext; _pos != (_head); _pos = _n, _n = _pos->pNext)
+
+typedef struct rpa_list_s
+{
+       struct rpa_list_s *pNext;
+       struct rpa_list_s *pPrev;
+} rpa_list_t, rpa_link_t, rpa_head_t;
+
+#ifdef WIN32
+
+void rpa_list_init(rpa_list_t *ptr);
+void rpa_list_check(rpa_list_t *ptr);
+void rpa_list_add(rpa_list_t *pNew, rpa_list_t *pPrev, rpa_list_t *pNext);
+void rpa_list_addh(rpa_list_t *pHead, rpa_list_t *pNew);
+void rpa_list_addt(rpa_list_t *pHead, rpa_list_t *pNew);
+void rpa_list_unlink(rpa_list_t *pPrev, rpa_list_t *pNext);
+void rpa_list_del(rpa_list_t *pEntry);
+rpa_list_t *rpa_list_first(rpa_list_t *pHead);
+rpa_list_t *rpa_list_last(rpa_list_t *pHead);
+rpa_list_t *rpa_list_prev(rpa_list_t *pHead, rpa_list_t *pElem);
+rpa_list_t *rpa_list_next(rpa_list_t *pHead, rpa_list_t *pElem);
+void rpa_list_splice(rpa_list_t *pList, rpa_list_t *pHead);
+int rpa_list_count(rpa_list_t *pHead);
+
+
+#else
+
+
+static inline void rpa_list_init(rpa_list_t *ptr)
+{
+       ptr->pNext = ptr; 
+       ptr->pPrev = ptr;
+}
+
+
+static inline void rpa_list_add(rpa_list_t *pNew, rpa_list_t *pPrev, rpa_list_t *pNext)
+{
+       pNext->pPrev = pNew;
+       pNew->pNext = pNext;
+       pNew->pPrev = pPrev;
+       pPrev->pNext = pNew;
+}
+
+
+static inline void rpa_list_addh(rpa_list_t *pHead, rpa_list_t *pNew)
+{
+       rpa_list_add(pNew, pHead, (pHead)->pNext);
+}
+
+
+static inline void rpa_list_addt(rpa_list_t *pHead, rpa_list_t *pNew)
+{
+       rpa_list_add(pNew, (pHead)->pPrev, pHead);
+}
+
+
+static inline void rpa_list_unlink(rpa_list_t *pPrev, rpa_list_t *pNext)
+{
+       pNext->pPrev = pPrev;
+       pPrev->pNext = pNext;
+}
+
+
+static inline void rpa_list_del(rpa_list_t *pEntry) 
+{
+       rpa_list_unlink((pEntry)->pPrev, (pEntry)->pNext);
+}
+
+
+static inline rpa_list_t *rpa_list_first(rpa_list_t *pHead) 
+{
+       return (((pHead)->pNext != (pHead)) ? (pHead)->pNext : ((void*)0));
+}
+
+
+static inline rpa_list_t *rpa_list_last(rpa_list_t *pHead)
+{
+       return (((pHead)->pPrev != (pHead)) ? (pHead)->pPrev : ((void*)0));
+}
+
+
+static inline rpa_list_t *rpa_list_prev(rpa_list_t *pHead, rpa_list_t *pElem)
+{
+       return (pElem && pElem->pPrev != pHead) ? (pElem)->pPrev: ((void*)0);
+}
+
+
+static inline rpa_list_t *rpa_list_next(rpa_list_t *pHead, rpa_list_t *pElem)
+{
+       return (pElem && pElem->pNext != pHead) ? pElem->pNext: ((void*)0);
+}
+
+
+static inline void rpa_list_splice(rpa_list_t *pList, rpa_list_t *pHead)
+{
+       rpa_list_t *pFirst;
+
+       pFirst = pList->pNext;
+       if (pFirst != pList) {
+               rpa_list_t *pLast = pList->pPrev;
+               rpa_list_t *pAt = pHead->pNext;
+               pFirst->pPrev = pHead;
+               pHead->pNext = pFirst;
+               pLast->pNext = pAt;
+               pAt->pPrev = pLast;
+       }
+}
+
+
+static inline int rpa_list_count(rpa_list_t *pHead)
+{
+       rpa_list_t *pCur;
+       int n = 0;
+
+       rpa_list_for_each(pCur, pHead)
+               n++;
+       return n;
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/rpa/rpamatch.c b/rpa/rpamatch.c
new file mode 100644 (file)
index 0000000..02516ce
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include "rpamatch.h"
+#include "rpamatchlist.h"
+#include "rpastring.h"
+#include "rpamem.h"
+#include "rpautf.h"
+#include "rpastat.h"
+
+
+static unsigned int rpa_match_getid(rpa_class_t *cls)
+{
+       return (RPA_MATCH_CLASSID);
+}
+
+
+static const char *rpa_match_getstr(rpa_class_t *cls)
+{
+       return "match";
+}
+
+
+static int rpa_match_dump(rpa_class_t *cls, char *buffer, unsigned int size)
+{
+       return 0;
+}
+
+
+static void rpa_match_destroy(rpa_class_t *cls)
+{
+       rpa_match_t *match = (rpa_match_t*)cls;
+       rpa_match_cleanup(match);
+       rpa_free(match);
+}
+
+
+static rpa_class_methods_t rpa_match_methods = {
+       rpa_match_getid,
+       rpa_match_getstr,
+       rpa_match_dump,
+       rpa_match_destroy,
+};
+
+
+void rpa_match_setup_name(
+       rpa_match_t *match, 
+       const char *name,
+       unsigned int namesiz)
+{
+       if (match->name) {
+               rpa_free(match->name);
+       }
+       if (!name) {
+               namesiz = 0;
+               match->name = (void*)0;
+               return;         
+       }
+       match->name = rpa_malloc(namesiz + 1);
+       match->namesiz = namesiz;
+       rpa_memset(match->name, 0, namesiz + 1);
+       if (name)
+               rpa_strncpy(match->name, name, namesiz);                
+}
+
+
+rpa_match_t *rpa_match_init(
+       rpa_match_t *match, 
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id,
+       rpa_class_methods_t *vptr)
+{
+       rpa_memset(match, 0, sizeof(*match));
+       rpa_class_init((rpa_class_t*)match, vptr);
+       match->match_function_id = match_function_id;
+       rpa_match_setup_name(match, name, namesiz);
+       return match;
+}
+
+
+void rpa_match_cleanup(rpa_match_t *match)
+{
+       rpa_free(match->name);
+}
+
+
+rpa_match_t * rpa_match_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id)
+{
+       rpa_match_t *newMatch;
+       
+       newMatch = (rpa_match_t *)rpa_malloc(sizeof(*newMatch));
+       if (!newMatch)
+               return ((void*)0);
+       rpa_memset(newMatch, 0, sizeof(*newMatch));
+       return rpa_match_init(newMatch, name, namesiz, match_function_id, &rpa_match_methods);
+}
+
+
+rpa_match_t *rpa_match_create(
+       const char *name,
+       rpa_matchfunc_t match_function_id)
+{
+       return rpa_match_create_namesize(name, rpa_strlen(name), match_function_id);
+}
+
+void rpa_match_set_mathfunc(rpa_match_t *match, rpa_matchfunc_t match_function_id)
+{
+       match->match_function_id = match_function_id;
+}
+
+
+int rpa_match_newline(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0;
+       unsigned int wc;        
+
+       if (input == stat->start || *(input - 1) == '\n') {
+               ret = rpa_stat_getchar(&wc, stat, input);
+               if (ret < 0)
+                       ret = 1;
+       }
+       return ret;
+}
+
+
+int rpa_match_lstchr(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0;
+       unsigned int wc;
+
+       ret = rpa_stat_getchar(&wc, stat, input);
+       if (ret < 0)
+               return 0;
+       if (input + ret == stat->end) {
+               return ret;
+       }
+       return 0;
+}
+
+
+int rpa_match_abort(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_stat_abort(stat);
+       return 0;
+}
+
+
+int rpa_match_fail(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       stat->fail = 1;
+       rpa_stat_abort(stat);
+       return 0;
+}
+
+
+int rpa_match_chreqany(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       unsigned int c;
+       int ret;
+
+       ret = rpa_stat_getchar(&c, stat, input);
+       if (ret < 0)
+               return 0;
+       return ret;
+}
+
+
+int rpa_match_scan_utf8(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0, inc = 0;
+       unsigned int wc;
+       const char *end = stat->end;
+       const char *start = stat->start;
+       const char *lastprogress = 0;
+
+MATCHAGAIN:
+       if (input >= stat->end) {
+               if (stat->fail && input < end) {
+                       stat->end = end;
+                       stat->fail = 0;
+               } else {
+                       return 0;
+               }
+       }
+       if (stat->progress && (input - lastprogress) > RPA_MIN_PROGRESS) {
+               lastprogress = input;
+               stat->progress(stat->progress_userdata, input, start, end);
+       }
+       inc = rpa_utf8_mbtowc(&wc, (const unsigned char*)input, (const unsigned char*)end);
+       if (inc <= 0)           
+               inc = 1;
+       ret = stat->mtable[match->match_function_id](match, stat, input);
+       if (!ret) {
+               input += inc;
+               goto MATCHAGAIN;
+       }
+       if (ret)
+               stat->where = input;
+       return ret;
+}
+
+
+int rpa_match_scan_utf8_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0, inc = 0;
+       unsigned int wc;
+       const char *end = stat->end;
+       const char *start = stat->start;
+       const char *lastprogress = 0;
+
+MATCHAGAIN:
+       if (input >= stat->end) {
+               if (stat->fail && input < end) {
+                       stat->end = end;
+                       stat->fail = 0;
+               } else {
+                       return 0;
+               }
+       }
+       if (stat->progress && (input - lastprogress) > RPA_MIN_PROGRESS) {
+               lastprogress = input;
+               stat->progress(stat->progress_userdata, input, start, end);
+       }
+       inc = rpa_utf8_mbtowc(&wc, (const unsigned char*)input, (const unsigned char*)end);
+       if (inc <= 0)           
+               inc = 1;
+       ret = stat->mtable[match->match_function_id](match, stat, input);
+       if (!ret) {
+               input += inc;
+               goto MATCHAGAIN;
+       }
+
+       if (ret)
+               stat->where = input;
+       return ret;
+}
+
+
+int rpa_match_scan_utf16(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0;
+       const char *end = stat->end;
+       const char *start = stat->start;
+       const char *lastprogress = 0;
+
+MATCHAGAIN:
+       if (input >= stat->end) {
+               if (stat->fail && input < end) {
+                       stat->end = end;
+                       stat->fail = 0;
+               } else {
+                       return 0;
+               }
+       }
+       if (stat->progress && (input - lastprogress) > RPA_MIN_PROGRESS) {
+               lastprogress = input;
+               stat->progress(stat->progress_userdata, input, start, end);
+       }
+       ret = stat->mtable[match->match_function_id](match, stat, input);
+       if (!ret) {
+               input += 2;
+               goto MATCHAGAIN;
+       }
+       if (ret)
+               stat->where = input;
+       return ret;
+}
+
+
+int rpa_match_scan_utf16_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0;
+       const char *end = stat->end;
+       const char *start = stat->start;
+       const char *lastprogress = 0;
+
+MATCHAGAIN:
+       if (input >= stat->end) {
+               if (stat->fail && input < end) {
+                       stat->end = end;
+                       stat->fail = 0;
+               } else {
+                       return 0;
+               }
+       }
+       if (stat->progress && (input - lastprogress) > RPA_MIN_PROGRESS) {
+               lastprogress = input;
+               stat->progress(stat->progress_userdata, input, start, end);
+       }
+       ret = stat->mtable[match->match_function_id](match, stat, input);
+       if (!ret) {
+               input += 2;
+               goto MATCHAGAIN;
+       }
+       if (ret)
+               stat->where = input;
+       return ret;
+}
+
+
+int rpa_match_scan_byte(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0;
+       const char *end = stat->end;
+       const char *start = stat->start;
+       const char *lastprogress = 0;
+
+MATCHAGAIN:
+       if (input >= stat->end) {
+               if (stat->fail && input < end) {
+                       stat->end = end;
+                       stat->fail = 0;
+               } else {
+                       return 0;
+               }
+       }
+       if (stat->progress && (input - lastprogress) > RPA_MIN_PROGRESS) {
+               lastprogress = input;
+               stat->progress(stat->progress_userdata, input, start, end);
+       }
+       ret = stat->mtable[match->match_function_id](match, stat, input);
+       if (!ret) {
+               input += 1;
+               goto MATCHAGAIN;
+       }
+       if (ret)
+               stat->where = input;
+       return ret;
+}
+
+
+int rpa_match_scan_byte_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0;
+       const char *end = stat->end;
+       const char *start = stat->start;
+       const char *lastprogress = 0;
+
+MATCHAGAIN:
+       if (input >= stat->end) {
+               if (stat->fail && input < end) {
+                       stat->end = end;
+                       stat->fail = 0;
+               } else {
+                       return 0;
+               }
+       }
+       if (stat->progress && (input - lastprogress) > RPA_MIN_PROGRESS) {
+               lastprogress = input;
+               stat->progress(stat->progress_userdata, input, start, end);
+       }
+       ret = stat->mtable[match->match_function_id](match, stat, input);
+       if (!ret) {
+               input += 1;
+               goto MATCHAGAIN;
+       }
+       if (ret)
+               stat->where = input;
+       return ret;
+}
diff --git a/rpa/rpamatch.h b/rpa/rpamatch.h
new file mode 100644 (file)
index 0000000..29577f6
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPAMATCH_H_
+#define _RPAMATCH_H_
+
+#include <stdarg.h>
+#include "rpaclass.h"
+#include "rpalist.h"
+#include "rpatypes.h"
+#include "rpawordstack.h"
+#include "rpatypedef.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These are the regular expression (regex) occurence flags:
+ * RPA_MATCH_NONE     - no flags, the pattern will be matched only once
+ * RPA_MATCH_MULTIPLE - (regex +) multiple flag means the pattern will be matched at least once,
+ *     but if it occurs more then once the consecutive occurrances will also be matched. If the regex
+ *     has something like .+ (match anything) it will match absolutely anything until the end of the
+ *     buffer is reached.
+ * RPA_MATCH_OPTIONAL - (regex ?) optional flag means the pattern might not be matched. If the pattern
+ *     is not encountered, the matching algorithm moves on to the next pattern.
+ * RPA_MATCH_OPTIONAL | RPA_MATCH_MULTIPLE - (regex *) The pattern might be encountered once, more than
+ *     once or not at all.
+ * 
+ * Short description of regex metachars:
+ * ? - zero or one  (RPA_MATCH_OPTIONAL)
+ * + - one or more  (RPA_MATCH_MULTIPLE)
+ * * - zero or more (RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE)
+ */
+#define RPA_MATCH_NONE 0
+#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 RPA_MATCH_MULTIOPT
+#define RPA_MNODE_CALLBACK (1 << 2)
+#define RPA_MNODE_LOOP (1 << 3)
+#define RPA_MNODEFUNC_MASK ((1 << 3) - 1)
+#define RPA_MNODE_SYNCRONOUS (1 << 4)
+#define RPA_MNODE_NOCONNECT (1 << 5)
+/* This definition is used to initialize a const on the stack that will be used
+ * for stack usage measurement. The content of the const is not important and it
+ * is not used in the measurement algorithm. It might be used for debugging
+ * purposes though.
+ */
+#define RPA_STACK_MARK 'M'
+#define RPA_MIN_PROGRESS 1024
+
+typedef enum rpa_matchfunc_s {
+       RPA_MATCHFUNC_NONE = 0,
+       RPA_MATCHFUNC_LIST,
+       RPA_MATCHFUNC_LIST_ALT,
+       RPA_MATCHFUNC_LIST_NOALT,       
+       RPA_MATCHFUNC_LIST_AND,
+       RPA_MATCHFUNC_LIST_MINUS,
+       RPA_MATCHFUNC_LIST_NOT,
+       RPA_MATCHFUNC_LIST_CONTAIN,
+       RPA_MATCHFUNC_LIST_AT,
+       RPA_MATCHFUNC_NLIST_ALT,
+       RPA_MATCHFUNC_NLIST_BESTALT,
+       RPA_MATCHFUNC_NEWLINE,
+       RPA_MATCHFUNC_CHREQANY,
+       RPA_MATCHFUNC_LSTCHR,
+       RPA_MATCHFUNC_ABORT,
+       RPA_MATCHFUNC_FAIL,
+       RPA_MATCHFUNC_VAL_CHREQ,
+       RPA_MATCHFUNC_VAL_CHRNOTEQ,
+       RPA_MATCHFUNC_RANGE_CHRINRANGE,
+       RPA_MATCHFUNC_RANGE_CHRNOTINRANGE,
+       RPA_MATCHFUNC_STR,
+       RPA_MATCHFUNC_STR_CHRINSTR,
+       RPA_MATCHFUNC_STR_CHRNOTINSTR,
+       RPA_MATCHFUNC_SCAN,
+} rpa_matchfunc_t;
+
+
+enum rpa_match_class_e {
+       MATCH_CLASS_NONE = 0,
+       MATCH_CLASS_MATCHPTR = 1,
+       MATCH_CLASS_NAMEDMATCHPTR,
+       MATCH_CLASS_MNODEPTR,
+       MATCH_CLASS_CALLBACKPTR,
+       MATCH_CLASS_DATAPTR,
+};
+
+
+struct rpa_match_s {
+       rpa_class_t cls;
+       char *name;
+       unsigned int namesiz;
+       unsigned int match_function_id;
+};
+
+
+rpa_match_t *rpa_match_init(
+       rpa_match_t *match, 
+       const char *name,
+       unsigned int namesize,
+       rpa_matchfunc_t match_function_id,
+       rpa_class_methods_t *vptr);
+rpa_match_t *rpa_match_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id);
+rpa_match_t *rpa_match_create(
+       const char *name,
+       rpa_matchfunc_t match_function_id);
+void rpa_match_setup_name(
+       rpa_match_t *match, 
+       const char *name,
+       unsigned int namesiz);
+void rpa_match_cleanup(rpa_match_t *match);
+void rpa_match_clear_cache(rpa_match_t *match);
+void rpa_match_set_mathfunc(rpa_match_t *match, rpa_matchfunc_t match_function_id);
+int rpa_match_exec(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_exec_nocache(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+
+int rpa_match_newline(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_lstchr(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_abort(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_fail(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_chreqany(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_scan_byte(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_scan_byte_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_scan_utf8(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_scan_utf8_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_scan_utf16(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_scan_utf16_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+
+rpa_word_t rpa_sdbm_hash_3(rpa_word_t c1, rpa_word_t c2, rpa_word_t c3);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpa/rpamatchlist.c b/rpa/rpamatchlist.c
new file mode 100644 (file)
index 0000000..b77e997
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include "rpamatch.h"
+#include "rpamnode.h"
+#include "rpamatchlist.h"
+#include "rpastring.h"
+#include "rpamem.h"
+#include "rpastat.h"
+#include "rpasearch.h"
+
+
+static unsigned int rpa_match_list_getid(rpa_class_t *cls)
+{
+       return (RPA_MATCH_LIST_CLASSID | RPA_MATCH_CLASSID);
+}
+
+
+static const char *rpa_match_list_getstr(rpa_class_t *cls)
+{
+       return "list";
+}
+
+
+static int rpa_match_list_dump(rpa_class_t *cls, char *buffer, unsigned int size)
+{
+       return 0;
+}
+
+
+static void rpa_match_list_destroy(rpa_class_t *cls)
+{
+       rpa_match_t *match = (rpa_match_t *)cls;
+       rpa_match_list_cleanup(match);
+       rpa_free(match);
+}
+
+static rpa_class_methods_t rpa_match_list_methods = {
+       rpa_match_list_getid,
+       rpa_match_list_getstr,
+       rpa_match_list_dump,
+       rpa_match_list_destroy,
+};
+
+
+void rpa_match_list_cleanup(rpa_match_t *match)
+{
+       rpa_match_list_cleanup_dataptr(match);
+       rpa_match_cleanup(match);
+}
+
+rpa_match_t *rpa_match_list_init(
+       rpa_match_t *matchlist, 
+       const char *name,
+       unsigned int namesiz,
+       rpa_class_methods_t *vptr,
+       rpa_matchfunc_t match_function_id)
+{
+       rpa_match_init(matchlist, name, namesiz, match_function_id, vptr);
+       rpa_list_init(&((rpa_match_list_t*)matchlist)->head);
+       rpa_match_list_init_dataptr(matchlist, name, namesiz, vptr, match_function_id);
+       return matchlist;
+}
+
+
+rpa_match_t * rpa_match_list_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id)
+{
+       rpa_match_list_t *newMatch;
+       newMatch = (rpa_match_list_t *)rpa_malloc(sizeof(*newMatch));
+       if (!newMatch)
+               return ((void*)0);
+       rpa_memset(newMatch, 0, sizeof(*newMatch));
+       return rpa_match_list_init((rpa_match_t*)newMatch, name, namesiz, (rpa_class_methods_t*)&rpa_match_list_methods, match_function_id);
+}
+
+
+rpa_match_t * rpa_match_list_create(const char *name, rpa_matchfunc_t match_function_id)
+{
+       return rpa_match_list_create_namesize(name, rpa_strlen(name), match_function_id);
+}
+
+
+int rpa_match_list(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_head_t *head;
+       const char *initial;
+       rpa_list_t *pos;
+       rpa_mnode_t *hcur;
+       int ret;
+
+       if (!stat->checkstack(stat))
+               return 0;
+       initial = input;
+       head = &((rpa_match_list_t *)match)->head;
+       rpa_list_for_each(pos, head) {
+               hcur = rpa_list_entry(pos, rpa_mnode_t, mlink);
+               ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input);
+               if (ret < 0)
+                       return 0;               
+               input += ret;
+               if (!ret && !(hcur->flags & RPA_MATCH_OPTIONAL))
+                       return 0;
+       }
+       return (int)(input - initial);
+}
+
+
+int rpa_match_list_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       /* 
+        * TBD. The rpa_match_list_icase probably needs to go away.
+        */
+       return rpa_match_list(match, stat, input);
+}
+
+
+
+int rpa_match_list_alt(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_head_t *head;
+       rpa_list_t *pos;
+       rpa_mnode_t *hcur;
+       int ret;
+
+       head = &((rpa_match_list_t *)match)->head;
+       rpa_list_for_each(pos, head) {
+               hcur = rpa_list_entry(pos, rpa_mnode_t, mlink);
+               ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input);
+               if (ret > 0)
+                       return ret;
+       }
+       return 0;
+}
+
+
+int rpa_match_list_best_alt(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_head_t *head;
+       rpa_list_t *pos;
+       rpa_mnode_t *hcur;
+       int ret, mret = 0;
+
+       head = &((rpa_match_list_t *)match)->head;
+       rpa_list_for_each(pos, head) {
+               hcur = rpa_list_entry(pos, rpa_mnode_t, mlink);
+               ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input);
+               if (ret > mret)
+                       mret = ret;
+       }
+       return mret;
+}
+
+
+
+int rpa_match_list_noalt(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_head_t *head;
+       rpa_list_t *pos;
+       rpa_mnode_t *hcur;
+       int ret;
+       unsigned int wc;
+
+       head = &((rpa_match_list_t *)match)->head;
+       rpa_list_for_each(pos, head) {
+               hcur = rpa_list_entry(pos, rpa_mnode_t, mlink);
+               ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input);
+               if (ret > 0)
+                       return 0;
+       }
+       ret = rpa_stat_getchar(&wc, stat, input);
+       if (ret < 0)
+               ret = 0;
+       return ret;     
+}
+
+
+int rpa_match_list_alt_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_head_t *head;
+       rpa_list_t *pos;
+       rpa_mnode_t *hcur;
+       int ret;
+
+       head = &((rpa_match_list_t *)match)->head;
+       rpa_list_for_each(pos, head) {
+               hcur = rpa_list_entry(pos, rpa_mnode_t, mlink);
+               ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input);
+               if (ret > 0)
+                       return ret;
+       }
+       return 0;
+}
+
+
+
+int rpa_match_list_and(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_head_t *head;
+       rpa_list_t *pos;
+       rpa_mnode_t *hcur;
+       int ret = 0;
+       
+       head = &((rpa_match_list_t *)match)->head;
+       rpa_list_for_each(pos, head) {
+               hcur = rpa_list_entry(pos, rpa_mnode_t, mlink);
+               ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input);
+               if (ret <= 0)
+                       return 0;
+       }
+       return ret;
+}
+
+
+int rpa_match_list_and_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_head_t *head;
+       rpa_list_t *pos;
+       rpa_mnode_t *hcur;
+       int ret = 0;
+       
+       head = &((rpa_match_list_t *)match)->head;
+       rpa_list_for_each(pos, head) {
+               hcur = rpa_list_entry(pos, rpa_mnode_t, mlink);
+               ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input);
+               if (ret <= 0)
+                       return 0;
+       }
+       return ret;
+}
+
+
+int rpa_match_list_contain(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_head_t *head;
+       rpa_list_t *first, *second;
+       rpa_mnode_t *hcur;
+       const char *savedend = stat->end;
+       int ret, mret;
+
+       head = &((rpa_match_list_t *)match)->head;
+       if (!(first = rpa_list_first(head)))
+               return 0;
+       if (!(second = rpa_list_next(head, first)))
+               return 0;
+       hcur = rpa_list_entry(first, rpa_mnode_t, mlink);
+       ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input);
+       if (ret <= 0)
+               return 0;
+       stat->end = input + ret;
+       hcur = rpa_list_entry(second, rpa_mnode_t, mlink);
+       mret = stat->mtable[RPA_MATCHFUNC_SCAN](hcur->match, stat, input);
+       /* Restore the end of buffer, if it is not set ot 0 (abort operation) */
+       if (stat->end)
+               stat->end = savedend;
+       if (!mret)
+               return 0;
+       return ret;
+}
+
+
+
+int rpa_match_list_at(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_head_t *head;
+       rpa_list_t *first, *second;
+       rpa_mnode_t *hcur;
+       const char *savedend = stat->end;
+       int ret;
+
+       head = &((rpa_match_list_t *)match)->head;
+       if (!(first = rpa_list_first(head)))
+               return 0;
+       if (!(second = rpa_list_next(head, first)))
+               return 0;
+       hcur = rpa_list_entry(second, rpa_mnode_t, mlink);
+       ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input);
+       if (ret <= 0)
+               return 0;
+       stat->end = input + ret;
+       hcur = rpa_list_entry(first, rpa_mnode_t, mlink);
+       ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input);
+       if (stat->end)
+               stat->end = savedend;
+       if (ret <= 0)
+               return 0;
+       return ret;
+}
+
+/*
+int rpa_match_list_at_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_head_t *head;
+       rpa_list_t *first, *second;
+       rpa_mnode_t *hcur;
+       const char *savedend = stat->end;
+       int ret;
+
+       head = &((rpa_match_list_t *)match)->head;
+       if (!(first = rpa_list_first(head)))
+               return 0;
+       if (!(second = rpa_list_next(head, first)))
+               return 0;
+       hcur = rpa_list_entry(second, rpa_mnode_t, mlink);
+       ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input);
+       if (ret <= 0)
+               return 0;
+       stat->end = input + ret;
+       hcur = rpa_list_entry(first, rpa_mnode_t, mlink);
+       ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input);
+       if (stat->end)
+               stat->end = savedend;
+       if (ret <= 0)
+               return 0;
+       return ret;
+}
+*/
+
+int rpa_match_list_minus(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_head_t *head = &((rpa_match_list_t *)match)->head;
+       rpa_list_t *pos;
+       rpa_mnode_t *hcur;
+       int ret = 0, i = 0;
+
+       rpa_list_for_each(pos, head) {
+               hcur = rpa_list_entry(pos, rpa_mnode_t, mlink);
+               if (i++ == 0) {
+                       if ((ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input)) <= 0)
+                               return 0;
+               } else {
+                       if (stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input) > 0)
+                               return 0;
+               }
+       }
+       return ret;
+}
+
+
+int rpa_match_list_minus_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_head_t *head = &((rpa_match_list_t *)match)->head;
+       rpa_list_t *pos;
+       rpa_mnode_t *hcur;
+       int ret = 0, i = 0;
+
+       rpa_list_for_each(pos, head) {
+               hcur = rpa_list_entry(pos, rpa_mnode_t, mlink);
+               if (i++ == 0) {
+                       if ((ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input)) <= 0)
+                               return 0;
+               } else {
+                       if (stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input) > 0)
+                               return 0;
+               }
+       }
+       return ret;
+}
+
+
+int rpa_match_list_not(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       rpa_head_t *head = &((rpa_match_list_t *)match)->head;
+       rpa_list_t *pos;
+       rpa_mnode_t *hcur;
+       int ret;
+       unsigned int wc;
+
+       rpa_list_for_each(pos, head) {
+               hcur = rpa_list_entry(pos, rpa_mnode_t, mlink);
+               ret = stat->ntable[hcur->flags & RPA_MNODEFUNC_MASK](hcur, stat, input);
+               if (ret > 0)
+                       return 0;
+       }
+       
+       ret = rpa_stat_getchar(&wc, stat, input);
+       if (ret < 0)
+               ret = 0;
+       return ret;
+}
+
+
+static unsigned int rpa_match_nlist_getid(rpa_class_t *cls)
+{
+       return (RPA_MATCH_NLIST_CLASSID | RPA_MATCH_LIST_CLASSID | RPA_MATCH_CLASSID);
+}
+
+
+static const char *rpa_match_nlist_getstr(rpa_class_t *cls)
+{
+       return "nlist";
+}
+
+
+static int rpa_match_nlist_dump(rpa_class_t *cls, char *buffer, unsigned int size)
+{
+       return 0;
+}
+
+
+static void rpa_match_nlist_destroy(rpa_class_t *cls)
+{
+       rpa_match_list_destroy(cls);
+}
+
+static rpa_class_methods_t rpa_match_nlist_methods = {
+       rpa_match_nlist_getid,
+       rpa_match_nlist_getstr,
+       rpa_match_nlist_dump,
+       rpa_match_nlist_destroy,
+};
+
+
+rpa_match_t * rpa_match_nlist_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id)
+{
+       rpa_match_nlist_t *newMatch;
+       newMatch = (rpa_match_nlist_t *)rpa_malloc(sizeof(*newMatch));
+       if (!newMatch)
+               return ((void*)0);
+       rpa_memset(newMatch, 0, sizeof(*newMatch));
+       return rpa_match_list_init((rpa_match_t *)newMatch, name, namesiz, &rpa_match_nlist_methods, match_function_id);
+}
diff --git a/rpa/rpamatchlist.h b/rpa/rpamatchlist.h
new file mode 100644 (file)
index 0000000..0361dd2
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPAMATCHLIST_H_
+#define _RPAMATCHLIST_H_
+
+#include <stdarg.h>
+#include "rpalist.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct rpa_match_list_s {
+       rpa_match_t base;
+       rpa_head_t head;
+       void *dataptr;
+} rpa_match_list_t;
+
+
+typedef struct rpa_match_nlist_s {
+       rpa_match_list_t base;
+       unsigned char loopy;
+} rpa_match_nlist_t;
+
+rpa_match_t * rpa_match_list_create(const char *name, rpa_matchfunc_t match_function_id);
+rpa_match_t * rpa_match_list_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id);
+rpa_match_t *rpa_match_list_init(
+       rpa_match_t *match, 
+       const char *name, 
+       unsigned int namesiz,
+       rpa_class_methods_t *vptr,
+       rpa_matchfunc_t match_function_id);
+void rpa_match_list_cleanup(rpa_match_t *match);
+
+rpa_match_t *rpa_match_list_init_dataptr(
+       rpa_match_t *match, 
+       const char *name, 
+       unsigned int namesiz,
+       rpa_class_methods_t *vptr,
+       rpa_matchfunc_t match_function_id);
+void rpa_match_list_cleanup_dataptr(rpa_match_t *match);
+int rpa_match_list_scan(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_alt(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_noalt(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_and(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_minus(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_at(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_alt_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_and_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_minus_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_contain(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_not(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_utf8not(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_u16not(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_list_best_alt(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+
+
+rpa_match_t * rpa_match_nlist_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpa/rpamatchrange.c b/rpa/rpamatchrange.c
new file mode 100644 (file)
index 0000000..796a2f6
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include "rpamatch.h"
+#include "rpamatchrange.h"
+#include "rpastring.h"
+#include "rpamem.h"
+#include "rpastat.h"
+
+
+static unsigned int rpa_match_range_getid(rpa_class_t *cls)
+{
+       return (RPA_MATCH_RANGE_CLASSID | RPA_MATCH_CLASSID);
+}
+
+
+static const char *rpa_match_range_getstr(rpa_class_t *cls)
+{
+       return "range";
+}
+
+
+static int rpa_match_range_dump(rpa_class_t *cls, char *buffer, unsigned int size)
+{
+       return 0;
+}
+
+
+static void rpa_match_range_destroy(rpa_class_t *cls)
+{
+       rpa_match_t *match = (rpa_match_t*)cls;
+       rpa_match_range_cleanup(match);
+       rpa_free(match);
+}
+
+
+static rpa_class_methods_t rpa_match_range_methods = {
+       rpa_match_range_getid,
+       rpa_match_range_getstr,
+       rpa_match_range_dump,
+       rpa_match_range_destroy,
+};
+
+
+rpa_match_t *rpa_match_range_init(
+       rpa_match_t *match, 
+       const char *name,
+       unsigned int namesiz,
+       rpa_class_methods_t *vptr,
+       rpa_matchfunc_t match_function_id,
+       unsigned long low,
+       unsigned long high)
+{
+       rpa_match_init(match, name, namesiz, match_function_id, vptr);
+       ((rpa_match_range_t *)match)->low = low;
+       ((rpa_match_range_t *)match)->high = high;
+       ((rpa_match_range_t *)match)->icaselow = rpa_icasechar(low);
+       ((rpa_match_range_t *)match)->icasehigh = rpa_icasechar(high);
+       return match;
+}
+
+void rpa_match_range_cleanup(rpa_match_t *match)
+{
+       rpa_match_cleanup(match);
+}
+
+
+rpa_match_t * rpa_match_range_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id,
+       unsigned long low,
+       unsigned long high)
+{
+       rpa_match_range_t *newMatch;
+       
+       newMatch = (rpa_match_range_t *)rpa_malloc(sizeof(*newMatch));
+       if (!newMatch)
+               return ((void*)0);
+       rpa_memset(newMatch, 0, sizeof(*newMatch));
+       return rpa_match_range_init((rpa_match_t*)newMatch, name, namesiz, &rpa_match_range_methods, match_function_id, low, high);
+}
+
+
+rpa_match_t * rpa_match_range_create(
+       const char *name,
+       rpa_matchfunc_t match_function_id,
+       unsigned long low,
+       unsigned long high)
+{
+       return rpa_match_range_create_namesize(name, rpa_strlen(name), match_function_id, low, high);
+}
+
+
+int rpa_match_range_chrinrange(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       unsigned int c;
+       int ret;
+
+       ret = rpa_stat_getchar(&c, stat, input);
+       if (c >= ((rpa_match_range_t*)match)->low && c <= ((rpa_match_range_t*)match)->high)
+               return ret;
+       return 0;
+}
+
+
+int rpa_match_range_chrinrange_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       unsigned int c;
+       int ret;
+
+       ret = rpa_stat_getchar(&c, stat, input);
+       if (c >= ((rpa_match_range_t*)match)->low && c <= ((rpa_match_range_t*)match)->high)
+               return ret;
+       else if (c >= ((rpa_match_range_t*)match)->icaselow && c <= ((rpa_match_range_t*)match)->icasehigh)
+               return ret;
+               
+       return 0;
+}
+
+
+int rpa_match_range_chrnotinrange(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       unsigned int c;
+       int ret;
+
+       ret = rpa_stat_getchar(&c, stat, input);
+       if (c < ((rpa_match_range_t*)match)->low && c > ((rpa_match_range_t*)match)->high)
+               return ret;
+       return 0;
+}
+
+
+int rpa_match_range_chrnotinrange_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       unsigned int c;
+       int ret;
+
+       ret = rpa_stat_getchar(&c, stat, input);
+       if ((c < ((rpa_match_range_t*)match)->low && c > ((rpa_match_range_t*)match)->high) &&
+               (c < ((rpa_match_range_t*)match)->icaselow && c > ((rpa_match_range_t*)match)->icasehigh))
+               return ret;
+
+       return 0;
+}
diff --git a/rpa/rpamatchrange.h b/rpa/rpamatchrange.h
new file mode 100644 (file)
index 0000000..26b5ce0
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPAMATCHRANGE_H_
+#define _RPAMATCHRANGE_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct rpa_match_range_s {
+       rpa_match_t base;
+       unsigned int low;
+       unsigned int high;
+       unsigned int icaselow;
+       unsigned int icasehigh;
+} rpa_match_range_t;
+
+void rpa_match_range_cleanup(rpa_match_t *match);
+//void rpa_match_range_destroy(rpa_match_t *match);
+rpa_match_t *rpa_match_range_init(
+       rpa_match_t *match, 
+       const char *name,
+       unsigned int namesiz,
+       rpa_class_methods_t *vptr,
+       rpa_matchfunc_t match_function_id,
+       unsigned long low,
+       unsigned long high);
+rpa_match_t * rpa_match_range_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id,
+       unsigned long low,
+       unsigned long high);
+rpa_match_t * rpa_match_range_create(
+       const char *name,
+       rpa_matchfunc_t match_function_id,
+       unsigned long low,
+       unsigned long high);
+int rpa_match_range_chrinrange(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_range_chrnotinrange(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_range_chrinrange_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_range_chrnotinrange_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpa/rpamatchrangelist.c b/rpa/rpamatchrangelist.c
new file mode 100644 (file)
index 0000000..8184a57
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include "rpamatch.h"
+#include "rpamem.h"
+#include "rpastring.h"
+#include "rpamatchlist.h"
+
+static unsigned int rpa_match_rangelist_getid(rpa_class_t *cls)
+{
+       return (RPA_MATCH_RANGELIST_CLASSID | RPA_MATCH_LIST_CLASSID | RPA_MATCH_CLASSID);
+}
+
+
+static const char *rpa_match_rangelist_getstr(rpa_class_t *cls)
+{
+       return "rangelist";
+}
+
+
+static int rpa_match_rangelist_dump(rpa_class_t *cls, char *buffer, unsigned int size)
+{
+       return 0;
+}
+
+
+static void rpa_match_rangelist_destroy(rpa_class_t *cls)
+{
+       rpa_match_t *match = (rpa_match_t *)cls;
+       rpa_match_list_cleanup(match);
+       rpa_free(match);
+}
+
+static rpa_class_methods_t rpa_match_rangelist_methods = {
+       rpa_match_rangelist_getid,
+       rpa_match_rangelist_getstr,
+       rpa_match_rangelist_dump,
+       rpa_match_rangelist_destroy,
+};
+
+
+rpa_match_t * rpa_match_rangelist_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id)
+{
+       rpa_match_list_t *newMatch;
+       newMatch = (rpa_match_list_t *)rpa_malloc(sizeof(*newMatch));
+       if (!newMatch)
+               return ((void*)0);
+       rpa_memset(newMatch, 0, sizeof(*newMatch));
+       return rpa_match_list_init((rpa_match_t *)newMatch, name, namesiz, &rpa_match_rangelist_methods, match_function_id);
+}
+
+
+rpa_match_t * rpa_match_rangelist_create(const char *name, rpa_matchfunc_t match_function_id)
+{
+       return rpa_match_rangelist_create_namesize(name, rpa_strlen(name), match_function_id);
+}
diff --git a/rpa/rpamatchrangelist.h b/rpa/rpamatchrangelist.h
new file mode 100644 (file)
index 0000000..5a798c6
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPAMATCHRANGELIST_H_
+#define _RPAMATCHRANGELIST_H_
+
+#include <stdarg.h>
+#include "rpalist.h"
+#include "rpamatchlist.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+rpa_match_t * rpa_match_rangelist_create(const char *name, rpa_matchfunc_t match_function_id);
+rpa_match_t * rpa_match_rangelist_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpa/rpamatchspecial.c b/rpa/rpamatchspecial.c
new file mode 100644 (file)
index 0000000..41f6a18
--- /dev/null
@@ -0,0 +1,60 @@
+#include "rpamatch.h"
+#include "rpastring.h"
+#include "rpamem.h"
+
+
+static unsigned int rpa_match_special_getid(rpa_class_t *cls)
+{
+       return (RPA_MATCH_SPECIAL_CLASSID | RPA_MATCH_CLASSID);
+}
+
+
+static const char *rpa_match_special_getstr(rpa_class_t *cls)
+{
+       return "matchspecial";
+}
+
+
+static int rpa_match_special_dump(rpa_class_t *cls, char *buffer, unsigned int size)
+{
+       return 0;
+}
+
+
+static void rpa_match_special_destroy(rpa_class_t *cls)
+{
+       rpa_match_t *match = (rpa_match_t*)cls;
+       rpa_match_cleanup(match);
+       rpa_free(match);
+}
+
+
+static rpa_class_methods_t rpa_match_special_methods = {
+       rpa_match_special_getid,
+       rpa_match_special_getstr,
+       rpa_match_special_dump,
+       rpa_match_special_destroy,
+};
+
+
+rpa_match_t * rpa_match_special_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id)
+{
+       rpa_match_t *newMatch;
+       
+       newMatch = (rpa_match_t *)rpa_malloc(sizeof(*newMatch));
+       if (!newMatch)
+               return ((void*)0);
+       rpa_memset(newMatch, 0, sizeof(*newMatch));
+       return rpa_match_init(newMatch, name, namesiz, match_function_id, &rpa_match_special_methods);
+}
+
+
+rpa_match_t *rpa_match_special_create(
+       const char *name,
+       rpa_matchfunc_t match_function_id)
+{
+       return rpa_match_special_create_namesize(name, rpa_strlen(name), match_function_id);
+}
diff --git a/rpa/rpamatchspecial.h b/rpa/rpamatchspecial.h
new file mode 100644 (file)
index 0000000..59af5e8
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPAMATCHSPECIAL_H_
+#define _RPAMATCHSPECIAL_H_
+
+#include "rpamatch.h"
+
+rpa_match_t *rpa_match_special_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id);
+rpa_match_t *rpa_match_special_create(
+       const char *name,
+       rpa_matchfunc_t match_function_id);
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpa/rpamatchstr.c b/rpa/rpamatchstr.c
new file mode 100644 (file)
index 0000000..1f44e6e
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include "rpamatch.h"
+#include "rpamatchstr.h"
+#include "rpamem.h"
+#include "rpastring.h"
+#include "rpastat.h"
+
+
+static unsigned int rpa_match_str_getid(rpa_class_t *cls)
+{
+       return (RPA_MATCH_STR_CLASSID | RPA_MATCH_CLASSID);
+}
+
+
+static const char *rpa_match_str_getstr(rpa_class_t *cls)
+{
+       return "str";
+}
+
+
+static int rpa_match_str_dump(rpa_class_t *cls, char *buffer, unsigned int size)
+{
+       return 0;
+}
+
+
+static void rpa_match_str_destroy(rpa_class_t *cls)
+{
+       rpa_match_t *match = (rpa_match_t*)cls;
+       rpa_match_str_cleanup(match);
+       rpa_free(match);
+}
+
+static rpa_class_methods_t rpa_match_str_methods = {
+       rpa_match_str_getid,
+       rpa_match_str_getstr,
+       rpa_match_str_dump,
+       rpa_match_str_destroy,
+};
+
+
+rpa_match_t *rpa_match_str_init(
+       rpa_match_t *match, 
+       const char *name,
+       unsigned int namesiz,
+       rpa_class_methods_t *vptr,
+       rpa_matchfunc_t match_function_id)
+{
+       rpa_match_init(match, name, namesiz, match_function_id, vptr);
+       return (rpa_match_t *)match;
+}
+
+
+void rpa_match_str_cleanup(rpa_match_t *match)
+{
+       rpa_free(((rpa_match_str_t*)match)->str);
+       rpa_match_cleanup(match);
+}
+
+
+rpa_match_t * rpa_match_str_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id)
+{
+       rpa_match_str_t *newMatch;
+       
+       newMatch = (rpa_match_str_t *)rpa_malloc(sizeof(*newMatch) );
+       if (!newMatch)
+               return ((void*)0);
+       rpa_memset(newMatch, 0, sizeof(*newMatch));
+       return rpa_match_str_init((rpa_match_t*)newMatch, name, namesiz, &rpa_match_str_methods, match_function_id);
+}
+
+
+rpa_match_t * rpa_match_str_create(
+       const char *name,
+       rpa_matchfunc_t match_function_id)
+{
+       return rpa_match_str_create_namesize(name, rpa_strlen(name), match_function_id);
+}
+
+
+rpa_strval_t *rpa_match_str_alloc_strval(rpa_match_t *match, unsigned long count)
+{
+       rpa_match_str_t *matchstr = (rpa_match_str_t*)match;
+       if (matchstr->str)
+               rpa_free(matchstr->str);
+       matchstr->count = 0;
+       matchstr->str = (rpa_strval_t *) rpa_malloc(sizeof(rpa_strval_t) * (count + 1));
+       if (!matchstr->str)
+               return (void*)0;
+       matchstr->count = count;
+       return matchstr->str;
+}
+
+
+void rpa_match_str_setval(rpa_match_t *match, unsigned int val, rpa_word_t offset)
+{
+       rpa_match_str_t *matchstr = (rpa_match_str_t*)match;
+
+       if (matchstr->str) {
+               matchstr->str[offset].val = val;
+               matchstr->str[offset].icaseval = rpa_icasechar(val);
+       }
+}
+
+
+int rpa_match_str(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       int ret;
+       unsigned int c;
+       const char *initial = input;
+       rpa_match_str_t *strmatch = (rpa_match_str_t *)match;
+       rpa_strval_t *str = strmatch->str, *strend = str + strmatch->count;
+
+       while (str < strend) {
+               ret = rpa_stat_getchar(&c, stat, input);
+               if (c != str->val)
+                       return 0;
+               input += ret;
+               str++;
+       }
+       return (int)(input - initial);
+}
+
+
+int rpa_match_str_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       int ret;
+       unsigned int c;
+       const char *initial = input;
+       rpa_match_str_t *strmatch = (rpa_match_str_t *)match;
+       rpa_strval_t *str = strmatch->str, *strend = str + strmatch->count;
+
+       while (str < strend) {
+               ret = rpa_stat_getchar(&c, stat, input);
+               if (c != str->val && c != str->icaseval)
+                       return 0;
+               input += ret;
+               str++;
+       }
+       return (int)(input - initial);
+}
+
+
+int rpa_match_icase_str(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       return 0;
+}
+
+
+int rpa_match_str_chrinstr(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       return 0;
+}
+
+
+int rpa_match_icase_str_chrinstr(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       return 0;
+}
+
+
+int rpa_match_str_chrnotinstr(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       return 0;
+}
+
+
+int rpa_match_icase_str_chrnotinstr(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       return 0;
+}
diff --git a/rpa/rpamatchstr.h b/rpa/rpamatchstr.h
new file mode 100644 (file)
index 0000000..89aeac6
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPAMATCHSTR_H_
+#define _RPAMATCHSTR_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct rpa_strval_s {
+       unsigned int val;
+       unsigned int icaseval;
+} rpa_strval_t;
+
+
+typedef struct rpa_match_str_s {
+       rpa_match_t base;
+       rpa_word_t count;
+       rpa_strval_t *str;
+} rpa_match_str_t;
+
+
+void rpa_match_str_cleanup(rpa_match_t *match);
+rpa_match_t *rpa_match_str_init(
+       rpa_match_t *match, 
+       const char *name,
+       unsigned int namesiz,
+       rpa_class_methods_t *vptr,
+       rpa_matchfunc_t match_function_id);
+rpa_match_t * rpa_match_str_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id);
+rpa_match_t * rpa_match_str_create(
+       const char *name,
+       rpa_matchfunc_t match_function_id);
+rpa_strval_t *rpa_match_str_alloc_strval(rpa_match_t *match, unsigned long count);
+void rpa_match_str_setval(rpa_match_t *match, unsigned int val, rpa_word_t offset);
+int rpa_match_str(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_str_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_str_chrinstr(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_icase_str_chrinstr(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_str_chrnotinstr(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_icase_str_chrnotinstr(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpa/rpamatchval.c b/rpa/rpamatchval.c
new file mode 100644 (file)
index 0000000..06afd16
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include "rpamatch.h"
+#include "rpamatchval.h"
+#include "rpastring.h"
+#include "rpamem.h"
+#include "rpastat.h"
+
+
+static unsigned int rpa_match_val_getid(rpa_class_t *cls)
+{
+       return (RPA_MATCH_VAL_CLASSID | RPA_MATCH_CLASSID);
+}
+
+
+static const char *rpa_match_val_getstr(rpa_class_t *cls)
+{
+       return "val";
+}
+
+
+static int rpa_match_val_dump(rpa_class_t *cls, char *buffer, unsigned int size)
+{
+       int ret;
+       unsigned char mb[7];
+       rpa_memset(mb, 0, sizeof(mb));
+       ret = rpa_utf8_wctomb(((rpa_match_val_t*)cls)->val, (unsigned char *)buffer, size);
+       if (ret < 0)
+               return 0;
+       if (ret < (int)size)
+               buffer[ret] = 0;
+       return ret;
+}
+
+
+static void rpa_match_val_destroy(rpa_class_t *cls)
+{
+       rpa_match_t *match = (rpa_match_t*)cls;
+       rpa_match_val_cleanup(match);
+       rpa_free(match);
+}
+
+
+static rpa_class_methods_t rpa_match_val_methods = {
+       rpa_match_val_getid,
+       rpa_match_val_getstr,
+       rpa_match_val_dump,
+       rpa_match_val_destroy,
+};
+
+
+rpa_match_t *rpa_match_val_init(
+       rpa_match_t *match, 
+       const char *name,
+       unsigned int namesiz,
+       rpa_class_methods_t *vptr,
+       rpa_matchfunc_t match_function_id,
+       unsigned long val)
+{
+       rpa_match_init(match, name, namesiz, match_function_id, vptr);
+       ((rpa_match_val_t*)match)->val = val;
+       ((rpa_match_val_t*)match)->icaseval = rpa_icasechar(val);
+       return (rpa_match_t *)match;
+}
+
+
+void rpa_match_val_cleanup(rpa_match_t *match)
+{
+       rpa_match_cleanup(match);       
+}
+
+
+rpa_match_t * rpa_match_val_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id,
+       unsigned long val)
+{
+       rpa_match_val_t *newMatch;
+       
+       newMatch = (rpa_match_val_t *)rpa_malloc(sizeof(*newMatch));
+       if (!newMatch)
+               return ((void*)0);
+       rpa_memset(newMatch, 0, sizeof(*newMatch));
+       return rpa_match_val_init((rpa_match_t*)newMatch, name, namesiz, &rpa_match_val_methods, match_function_id, val);
+}
+
+
+rpa_match_t * rpa_match_val_create(
+       const char *name,
+       rpa_matchfunc_t match_function_id,
+       unsigned long val)
+{
+       return rpa_match_val_create_namesize(name, rpa_strlen(name), match_function_id, val);
+}
+
+
+int rpa_match_val_chreq(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       unsigned int c;
+       int ret;
+
+       ret = rpa_stat_getchar(&c, stat, input);
+       if (c == ((rpa_match_val_t*)match)->val)
+               return ret;
+       return 0;
+}
+
+
+int rpa_match_val_chrnoteq(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       unsigned int c;
+       int ret;
+
+       ret = rpa_stat_getchar(&c, stat, input);
+       if (c != ((rpa_match_val_t*)match)->val)
+               return ret;
+       return 0;
+}
+
+
+int rpa_match_val_chreq_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       unsigned int c;
+       int ret;
+
+       ret = rpa_stat_getchar(&c, stat, input);
+       if (c == ((rpa_match_val_t*)match)->val)
+               return ret;
+       else if (c == ((rpa_match_val_t*)match)->icaseval)
+               return ret;
+
+       return 0;
+}
+
+
+int rpa_match_val_chrnoteq_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input)
+{
+       unsigned int c;
+       int ret;
+
+       ret = rpa_stat_getchar(&c, stat, input);
+       if (c != ((rpa_match_val_t*)match)->val && c != ((rpa_match_val_t*)match)->icaseval)
+               return ret;
+       return 0;
+}
diff --git a/rpa/rpamatchval.h b/rpa/rpamatchval.h
new file mode 100644 (file)
index 0000000..8133cf1
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPAMATCHVAL_H_
+#define _RPAMATCHVAL_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct rpa_match_val_s {
+       rpa_match_t base;
+       unsigned int val;
+       unsigned int icaseval;
+} rpa_match_val_t;
+
+rpa_match_t * rpa_match_val_create_namesize(
+       const char *name,
+       unsigned int namesiz,
+       rpa_matchfunc_t match_function_id,
+       unsigned long val);
+rpa_match_t * rpa_match_val_create(
+       const char *name,
+       rpa_matchfunc_t match_function_id,
+       unsigned long val);
+rpa_match_t *rpa_match_val_init(
+       rpa_match_t *match, 
+       const char *name,
+       unsigned int namesiz,
+       rpa_class_methods_t *vptr,
+       rpa_matchfunc_t match_function_id,
+       unsigned long val);
+void rpa_match_val_cleanup(rpa_match_t *match);
+int rpa_match_val_chreq(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_val_chreq_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_val_chrnoteq(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+int rpa_match_val_chrnoteq_icase(rpa_match_t *match, rpa_stat_t *stat, const char *input);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpa/rpamem.c b/rpa/rpamem.c
new file mode 100644 (file)
index 0000000..84b0db4
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "rpatypes.h"
+#include "rpamem.h"
+
+long int g_rpa_allocmem = 0;
+long int g_rpa_maxmem = 0;
+
+
+void *rpa_malloc(unsigned long size)
+{
+#ifdef RPA_DEBUG_MEM
+       rpa_word_t *mem = NULL;
+       size += sizeof(rpa_word_t);
+       mem = (rpa_word_t*)malloc((size_t)(size));
+       *((rpa_word_t*)mem) = size;
+       g_rpa_allocmem += size;
+       if (g_rpa_maxmem < g_rpa_allocmem)
+               g_rpa_maxmem = g_rpa_allocmem;
+       mem += 1;
+       return (void*)mem;
+#else
+       return malloc((size_t)size);
+#endif
+}
+
+
+void *rpa_zmalloc(unsigned long size) {
+       void *mem;
+       
+       if ((mem = rpa_malloc(size)))
+               rpa_memset(mem, 0, size);
+       return mem;
+}
+
+void rpa_free(void *ptr)
+{
+#ifdef RPA_DEBUG_MEM
+       rpa_word_t *mem = (void*)(((rpa_word_t*)ptr) - 1);
+       rpa_word_t size;
+       if (!ptr)
+               return;
+       size = *mem;
+       g_rpa_allocmem -= size;
+//     fprintf(stdout, "%p (%ld de-allocated)\n", (void*)mem, size);
+       free((void*)mem);
+#else
+       free(ptr);
+#endif
+}
+
+
+void *rpa_realloc(void *ptr, unsigned long size)
+{
+#ifdef RPA_DEBUG_MEM
+       rpa_word_t *mem = (void*)(((rpa_word_t*)ptr) - 1);
+       rpa_word_t csize;
+       if (!ptr)
+               return rpa_malloc(size);
+       csize = *mem;
+       g_rpa_allocmem -= csize;
+       size += sizeof(long);
+       mem = (rpa_word_t*)realloc((void*)mem, (size_t)(size));
+       *mem = size;
+       g_rpa_allocmem += size;
+       if (g_rpa_maxmem < g_rpa_allocmem)
+               g_rpa_maxmem = g_rpa_allocmem;
+       mem += 1;
+       return (void*)mem;
+#else
+       return realloc(ptr, (size_t)size);
+#endif
+}
+
+
+void *rpa_memset(void *s, int c, unsigned long n)
+{
+       return memset(s, c, (size_t)n);
+}
+
+
+void *rpa_memcpy(void *dest, const void *src, unsigned long n)
+{
+       return memcpy(dest, src, (size_t)n);
+}
diff --git a/rpa/rpamem.h b/rpa/rpamem.h
new file mode 100644 (file)
index 0000000..a3883e1
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPAMEM_H_
+#define _RPAMEM_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern long int g_rpa_allocmem;
+extern long int g_rpa_maxmem;
+
+
+void *rpa_malloc(unsigned long size);
+void *rpa_zmalloc(unsigned long size);
+void rpa_free(void *ptr);
+void *rpa_realloc(void *ptr, unsigned long size);
+void *rpa_memset(void *s, int c, unsigned long n);
+void *rpa_memcpy(void *dest, const void *src, unsigned long n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpa/rpamnode.c b/rpa/rpamnode.c
new file mode 100644 (file)
index 0000000..4bc9b4f
--- /dev/null
@@ -0,0 +1,643 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include "rpamem.h"
+#include "rpastring.h"
+#include "rpamatch.h"
+#include "rpalist.h"
+#include "rpamatchlist.h"
+#include "rpamnode.h"
+#include "rpastat.h"
+#include "rpadbex.h"
+
+#define RPA_MAX_RECURSION 100
+#define RPA_DLOOP_INIT(__name__, __match__, __input__) {{&(__name__).lnk, &(__name__).lnk }, (__match__), (__input__), 0, 0}
+
+
+static unsigned int rpa_mnode_getid(rpa_class_t *cls)
+{
+       return (RPA_MNODE_CLASSID);
+}
+
+
+static const char *rpa_mnode_getstr(rpa_class_t *cls)
+{
+       if ((((rpa_mnode_t*)cls)->flags & (RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE)) == (RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE))
+               return "*";
+       else if (((rpa_mnode_t*)cls)->flags & RPA_MATCH_OPTIONAL)
+               return "?";
+       else if (((rpa_mnode_t*)cls)->flags & RPA_MATCH_MULTIPLE )
+               return "+";
+       else
+               return "x";
+
+       return "";
+}
+
+
+static int rpa_mnode_dump(rpa_class_t *cls, char *buffer, unsigned int size)
+{
+       return 0;
+}
+
+
+static void rpa_mnode_destroy(rpa_class_t *cls)
+{
+       rpa_mnode_t *mnode = (rpa_mnode_t*)cls;
+       rpa_free(mnode);
+}
+
+
+static rpa_class_methods_t rpa_mnode_methods = {
+       rpa_mnode_getid,
+       rpa_mnode_getstr,
+       rpa_mnode_dump,
+       rpa_mnode_destroy,
+};
+
+
+static rpa_class_methods_t rpa_mnode_callback_methods = {
+       rpa_mnode_getid,
+       rpa_mnode_getstr,
+       rpa_mnode_dump,
+       rpa_mnode_destroy,
+};
+
+
+int rpa_mnode_check_for_loop(rpa_mnode_t *mnode, rpa_match_t *loop, rpa_head_t *mhead, int reclevel)
+{
+       int ret = 0;
+       unsigned int classid = 0;
+       rpa_match_t *match = mnode->match;
+       rpa_dloop_t dloop;
+       rpa_link_t *pos;
+
+       if (reclevel > RPA_MAX_RECURSION)
+               return 0;
+               
+//     fprintf(stdout, "%s: %s\n", __FUNCTION__, match->name);
+       /* easy case */
+       if (reclevel && match == loop) {
+               mnode->flags |= RPA_MNODE_LOOP;
+               return 1;
+       }
+       
+       for (pos = rpa_list_last(mhead); pos; pos = rpa_list_prev(mhead, pos)) {
+               rpa_dloop_t *pLoop = rpa_list_entry(pos, rpa_dloop_t, lnk);
+               if (pLoop->match == match)
+                       return 0;
+       }       
+
+       rpa_list_init(&dloop.lnk);
+       dloop.match = match;
+       rpa_list_addt(mhead, &dloop.lnk);
+
+       classid = rpa_class_getid((rpa_class_t *)mnode->match);
+       if (classid & (RPA_MATCH_LIST_CLASSID|RPA_MATCH_NLIST_CLASSID)) {
+               rpa_mnode_t *hcur;
+               rpa_link_t *pos;
+               rpa_head_t *head = &((rpa_match_list_t *)match)->head;
+               switch (match->match_function_id) {
+                       case RPA_MATCHFUNC_LIST_ALT:
+                       case RPA_MATCHFUNC_NLIST_ALT:
+                       case RPA_MATCHFUNC_NLIST_BESTALT:
+                               rpa_list_for_each(pos, head) {
+                                       hcur = rpa_list_entry(pos, rpa_mnode_t, mlink);
+                                       if (rpa_mnode_check_for_loop(hcur, loop, mhead, reclevel + 1))
+                                               ret = 1;
+                               }
+                       break;
+                       case RPA_MATCHFUNC_LIST:
+                               rpa_list_for_each(pos, head) {
+                                       hcur = rpa_list_entry(pos, rpa_mnode_t, mlink);
+                                       if (rpa_mnode_check_for_loop(hcur, loop, mhead, reclevel + 1))
+                                               ret = 1;
+                                       if ((hcur->flags & RPA_MATCH_OPTIONAL) == 0)
+                                               break;
+                               }
+                       break;
+                       default:
+                               ret = 0;
+                       break;
+               }
+       }
+       
+       rpa_list_del(&dloop.lnk);
+
+       if (ret)
+               mnode->flags |= RPA_MNODE_LOOP; 
+       return ret;
+}
+
+
+rpa_mnode_t *rpa_mnode_init(
+       rpa_mnode_t *mnode,
+       rpa_match_t *match, 
+       unsigned int flags,
+       rpa_class_methods_t *vptr)
+{
+       rpa_memset(mnode, 0, sizeof(*mnode));
+       rpa_class_init((rpa_class_t*)mnode, vptr);
+       mnode->match = match;
+       mnode->flags = flags;
+       rpa_list_init(&mnode->mlink);
+       return mnode;
+}
+
+
+rpa_mnode_t *rpa_mnode_callback_init(
+       rpa_mnode_callback_t *mnode,
+       rpa_match_t *match, 
+       unsigned int flags,
+       RPA_MATCH_CALLBACK matched_callback, 
+       void *userdata,
+       rpa_class_methods_t *vptr)
+{
+       flags |= RPA_MNODE_CALLBACK; 
+       rpa_mnode_init((rpa_mnode_t*)mnode, match, flags, vptr);
+       mnode->matched_callback = matched_callback;
+       mnode->userdata = userdata;
+       return (rpa_mnode_t*)mnode;
+}
+
+rpa_mnode_t *rpa_mnode_create(
+       rpa_match_t *match, 
+       unsigned int flags)
+{
+       rpa_mnode_t *newnode;
+
+       newnode = (rpa_mnode_t*) rpa_malloc(sizeof(*newnode));
+       if (!newnode)
+               return ((void*)0);
+       return rpa_mnode_init(newnode, match, flags, &rpa_mnode_methods);
+}
+
+
+rpa_mnode_t *rpa_mnode_callback_create(
+       rpa_match_t *match, 
+       unsigned int flags, 
+       RPA_MATCH_CALLBACK matched_callback, 
+       void *userdata)
+{
+       rpa_mnode_callback_t *newnode;
+
+       newnode = (rpa_mnode_callback_t*) rpa_malloc(sizeof(*newnode));
+       if (!newnode)
+               return ((void*)0);
+       return rpa_mnode_callback_init(newnode, match, flags, matched_callback, userdata, &rpa_mnode_callback_methods);
+}
+
+
+rpa_mnode_t *rpa_mnode_callback_arg1_create(
+       rpa_match_t *match, 
+       unsigned int flags, 
+       RPA_MATCH_CALLBACK matched_callback, 
+       void *userdata,
+       rpa_word_t arg1)
+{
+       rpa_mnode_callback_arg1_t *newnode;
+
+       newnode = (rpa_mnode_callback_arg1_t*) rpa_malloc(sizeof(*newnode));
+       if (!newnode)
+               return ((void*)0);
+       newnode->arg1 = arg1;
+       return rpa_mnode_callback_init((rpa_mnode_callback_t*)newnode, match, flags, matched_callback, userdata, &rpa_mnode_callback_methods);
+       
+}
+
+
+rpa_mnode_t *rpa_mnode_callback_arg2_create(
+       rpa_match_t *match, 
+       unsigned int flags, 
+       RPA_MATCH_CALLBACK matched_callback, 
+       void *userdata,
+       rpa_word_t arg1,
+       rpa_word_t arg2)
+{
+       rpa_mnode_callback_arg2_t *newnode;
+
+       newnode = (rpa_mnode_callback_arg2_t*) rpa_malloc(sizeof(*newnode));
+       if (!newnode)
+               return ((void*)0);
+       newnode->base.arg1 = arg1;
+       newnode->arg2 = arg2;
+       return rpa_mnode_callback_init((rpa_mnode_callback_t*)newnode, match, flags, matched_callback, userdata, &rpa_mnode_callback_methods);
+}
+
+
+rpa_mnode_t *rpa_mnode_list_append(rpa_head_t *head, rpa_mnode_t *mnode)
+{
+       rpa_list_addt(head, &mnode->mlink);
+       return mnode;
+}
+
+
+void rpa_mnode_cat_list(rpa_head_t *head, rpa_mnode_t *first, ...)
+{
+       va_list args;
+       rpa_mnode_t *next;
+
+       va_start(args, first);
+       for (next = first; next; next = va_arg(args, rpa_mnode_t*)) {
+               rpa_mnode_list_append(head, next);
+       }
+       va_end(args);
+}
+
+
+int rpa_mnode_exec_callback(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       int ret = size;
+
+       if (input >= stat->end)
+               return -1;
+       if ( ((rpa_mnode_callback_t*)mnode)->matched_callback && (reason & mnode->flags))
+               ret = ((rpa_mnode_callback_t*)mnode)->matched_callback(mnode, stat, input, size, (reason & mnode->flags));
+       return ret;
+}
+
+
+int rpa_mnode_record_callback(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_cbrecord_t *cbrec;
+
+       if (input >= stat->end)
+               return -1;
+       if (mnode->flags & RPA_MNODE_SYNCRONOUS)
+               return rpa_mnode_exec_callback(mnode, stat, input, size, reason);
+       if ( ((rpa_mnode_callback_t*)mnode)->matched_callback) {
+               if ((cbrec = rpa_cbset_push(&stat->cbset)) != 0) {
+                       cbrec->mnode = mnode;
+                       cbrec->input = input;
+                       cbrec->size = size;
+               }
+       }
+       return size;
+}
+
+
+int rpa_mnode_plain(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret;
+       rpa_match_t *match = mnode->match;
+
+       if (stat->currentloop && stat->currentloop->size && stat->currentloop->input == input && !(mnode->flags & RPA_MNODE_LOOP))
+               return 0;
+
+       ret = stat->mtable[match->match_function_id](mnode->match, stat, input);
+       if (ret <= 0)
+               return -1;
+       return ret;
+}
+
+
+int rpa_mnode_optional(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret;
+       ret = rpa_mnode_plain(mnode, stat, input);
+       if (ret < 0)
+               return 0;
+       return ret;
+}
+
+
+int rpa_mnode_multiple(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0, mret;
+       
+       mret = rpa_mnode_plain(mnode, stat, input);
+       if (mret < 0)
+               return -1;
+       ret += mret;
+       while ((mret = rpa_mnode_optional(mnode, stat, input + ret))) {
+               ret += mret;
+       }
+       return ret;
+}
+
+
+int rpa_mnode_multiopt(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0, mret;
+       
+       while ((mret = rpa_mnode_optional(mnode, stat, input + ret))) {
+               ret += mret;
+       }
+       return ret;
+}
+
+
+
+int rpa_mnode_plain_loop_detect(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret;
+       rpa_dloop_t *pLoop;
+       rpa_match_t *match = mnode->match;
+       rpa_dloop_t loop = RPA_DLOOP_INIT(loop, match, input);
+       rpa_head_t *bucket = &stat->loophash[RPA_LOOPHASH(match)];
+       rpa_link_t *pos;
+
+       pLoop = rpa_stat_current_loop(stat);
+       if (pLoop && pLoop->match == mnode->match) {
+               return pLoop->size;
+       }
+
+       for (pos = rpa_list_last(bucket); pos; pos = rpa_list_prev(bucket, pos)) {
+               pLoop = rpa_list_entry(pos, rpa_dloop_t, lnk);
+               if (pLoop->match == match && pLoop->input == input) {
+                       pLoop->mnode = mnode;
+                       rpa_list_del(pos);
+                       rpa_list_addt(&stat->loopstack, pos);
+                       stat->currentloop = pLoop;
+                       return pLoop->size;
+               }
+       }
+
+       rpa_list_addt(bucket, &loop.lnk);
+       ret = stat->mtable[match->match_function_id](mnode->match, stat, input);
+       if (loop.mnode) {
+               while (ret > loop.size) {
+                       loop.size = ret;
+                       ret = stat->mtable[match->match_function_id](mnode->match, stat, input);
+               }
+       }
+       rpa_list_del(&loop.lnk);
+       stat->currentloop = rpa_stat_current_loop(stat);
+       if (loop.size)
+               ret = loop.size;
+       if (ret <= 0)
+               return -1;
+       return ret;
+}
+
+
+int rpa_mnode_callback_plain(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret;
+       rpa_match_t *match = mnode->match;
+       rpa_mcache_t *mcache = &stat->mcache[RPA_MCACHEHASH(match)];
+
+       rpa_mnode_exec_callback(mnode, stat, input, (unsigned int) (stat->end - input), RPA_REASON_START);
+       if (((rpa_match_nlist_t*)(mnode->match))->loopy) {
+               ret = rpa_mnode_plain_loop_detect(mnode, stat, input);
+       } else if (stat->usecache && mcache->match == match && mcache->input == input) {
+               ret = mcache->ret;
+       } else {
+               ret = rpa_mnode_plain(mnode, stat, input);
+       }
+       RPA_MCACHE_SET(mcache, match, input, ret);
+       if (ret <= 0) {
+               rpa_mnode_exec_callback(mnode, stat, input, 0, RPA_REASON_END);
+               return -1;
+       }
+       ret = rpa_mnode_exec_callback(mnode, stat, input, ret, RPA_REASON_END|RPA_REASON_MATCHED);
+       if (!ret) 
+               return -1;
+       return ret;
+}
+
+
+int rpa_mnode_callback_optional(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret;
+
+       ret = rpa_mnode_callback_plain(mnode, stat, input);
+       if (ret < 0) 
+               return 0;
+       
+       return ret;
+}
+
+
+int rpa_mnode_callback_multiple(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0, mret;
+
+       mret = rpa_mnode_callback_plain(mnode, stat, input);
+       if (mret <= 0) 
+               return mret;
+
+       ret += mret;
+       do {
+               mret = rpa_mnode_callback_optional(mnode, stat, input + ret);
+               ret += mret;
+       } while (mret);
+
+       return ret;
+}
+
+
+int rpa_mnode_callback_multiopt(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0, mret;
+
+       do {
+               mret = rpa_mnode_callback_optional(mnode, stat, input + ret);
+               ret += mret;
+       } while (mret);
+       
+       return ret;
+}
+
+
+
+/* Parser functionality */
+
+int rpa_mnode_p_plain_loop_detect(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret;
+       rpa_word_t off; 
+       rpa_dloop_t *pLoop;
+       rpa_match_t *match = mnode->match;
+       rpa_dloop_t loop = RPA_DLOOP_INIT(loop, match, input);
+       rpa_head_t *bucket = &stat->loophash[RPA_LOOPHASH(match)];
+       rpa_link_t *pos;
+
+       pLoop = rpa_stat_current_loop(stat);
+       if (pLoop && pLoop->match == mnode->match) {
+               return pLoop->size;
+       }
+
+       for (pos = rpa_list_last(bucket); pos; pos = rpa_list_prev(bucket, pos)) {
+               pLoop = rpa_list_entry(pos, rpa_dloop_t, lnk);
+               if (pLoop->match == match && pLoop->input == input) {
+                       pLoop->mnode = mnode;
+                       rpa_list_del(pos);
+                       rpa_list_addt(&stat->loopstack, pos);
+                       stat->currentloop = pLoop;
+                       return pLoop->size;
+               }
+       }
+
+       rpa_list_addt(bucket, &loop.lnk);
+       off = rpa_cbset_getpos(&stat->cbset);
+       ret = stat->mtable[match->match_function_id](mnode->match, stat, input);
+       if (ret <= 0)
+               rpa_cbset_reset(&stat->cbset, off);
+       if (loop.mnode) {
+               while (ret > loop.size) {
+                       loop.size = ret;
+                       off = rpa_cbset_getpos(&stat->cbset);
+                       ret = stat->mtable[match->match_function_id](mnode->match, stat, input);
+                       if (ret <= loop.size)
+                               rpa_cbset_reset(&stat->cbset, off);
+               }
+       }
+       rpa_list_del(&loop.lnk);
+       stat->currentloop = rpa_stat_current_loop(stat);
+       if (loop.size)
+               ret = loop.size;
+       if (ret <= 0)
+               return -1;
+
+       return ret;
+}
+
+
+
+int rpa_mnode_p_plain(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret;
+       rpa_word_t off = rpa_cbset_getpos(&stat->cbset);
+       rpa_match_t *match = mnode->match;
+
+       if (stat->currentloop && stat->currentloop->size && stat->currentloop->input == input && !(mnode->flags & RPA_MNODE_LOOP))
+               return 0;
+       ret = stat->mtable[match->match_function_id](mnode->match, stat, input);
+       if (ret <= 0) {
+               rpa_cbset_reset(&stat->cbset, off);
+               return -1;
+       }
+       return ret;
+}
+
+
+int rpa_mnode_p_optional(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret;
+       ret = rpa_mnode_p_plain(mnode, stat, input);
+       if (ret < 0)
+               return 0;
+       return ret;
+}
+
+
+int rpa_mnode_p_multiple(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0, mret;
+       
+       mret = rpa_mnode_p_plain(mnode, stat, input);
+       if (mret < 0)
+               return -1;
+       ret += mret;
+       while ((mret = rpa_mnode_p_optional(mnode, stat, input + ret))) {
+               ret += mret;
+       }
+       return ret;
+}
+
+
+int rpa_mnode_p_multiopt(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0, mret;
+       
+       while ((mret = rpa_mnode_p_optional(mnode, stat, input + ret))) {
+               ret += mret;
+       }
+       return ret;
+}
+
+
+int rpa_mnode_p_callback_plain(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret;
+       rpa_match_t *match = mnode->match;
+       rpa_mcache_t *mcache = &stat->mcache[RPA_MCACHEHASH(match)];
+       rpa_word_t cboffset = rpa_cbset_getpos(&stat->cbset);
+
+       if (((rpa_match_nlist_t*)match)->loopy) {
+               ret = rpa_mnode_p_plain_loop_detect(mnode, stat, input);
+       } else if (mcache->match == match && mcache->input == input) {
+               if (mcache->ret > 0)
+                       rpa_cbset_reset(&stat->cbset, mcache->cboffset);
+               ret = mcache->ret;
+       } else {
+               ret = rpa_mnode_p_plain(mnode, stat, input);
+       }
+
+       RPA_MCACHE_CBSET(mcache, match, input, ret, rpa_cbset_getpos(&stat->cbset));
+       if (cboffset > stat->highbound)
+               stat->highbound = cboffset;
+       
+       if (ret > 0) {
+               ret = rpa_mnode_record_callback(mnode, stat, input, ret, RPA_REASON_START|RPA_REASON_END|RPA_REASON_MATCHED);
+               if (!ret) 
+                       return -1;
+               rpa_stat_cache_cbreset(stat, rpa_cbset_getpos(&stat->cbset));
+       }
+       
+       if (ret <= 0) {
+               return -1;
+       }
+       return ret;
+}
+
+
+int rpa_mnode_p_callback_optional(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret;
+
+       ret = rpa_mnode_p_callback_plain(mnode, stat, input);
+       if (ret < 0) 
+               return 0;
+       
+       return ret;
+}
+
+
+int rpa_mnode_p_callback_multiple(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0, mret;
+
+       mret = rpa_mnode_p_callback_plain(mnode, stat, input);
+       if (mret <= 0) 
+               return mret;
+
+       ret += mret;
+       do {
+               mret = rpa_mnode_p_callback_optional(mnode, stat, input + ret);
+               ret += mret;
+       } while (mret);
+
+       return ret;
+}
+
+
+int rpa_mnode_p_callback_multiopt(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input)
+{
+       int ret = 0, mret;
+
+       do {
+               mret = rpa_mnode_p_callback_optional(mnode, stat, input + ret);
+               ret += mret;
+       } while (mret);
+       
+       return ret;
+}
diff --git a/rpa/rpamnode.h b/rpa/rpamnode.h
new file mode 100644 (file)
index 0000000..6cb15ca
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPAMNODE_H_
+#define _RPAMNODE_H_
+
+#include "rpamatch.h"
+#include "rpalist.h"
+#include "rpaclass.h"
+#include "rpatypedef.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct rpa_mnode_s {
+       rpa_class_t cls;
+       rpa_head_t mlink;
+       rpa_match_t *match;
+       unsigned int flags;
+};
+
+
+struct rpa_mnode_callback_s {
+       rpa_mnode_t base;
+       rpa_head_t cblink;              /* future use */
+       RPA_MATCH_CALLBACK matched_callback;
+       void *userdata;
+};
+
+
+typedef struct rpa_mnode_callback_arg1_s {
+       rpa_mnode_callback_t base;
+       rpa_word_t arg1;
+} rpa_mnode_callback_arg1_t;
+
+
+typedef struct rpa_mnode_callback_arg2_s {
+       rpa_mnode_callback_arg1_t base;
+       rpa_word_t arg2;
+} rpa_mnode_callback_arg2_t;
+
+
+rpa_mnode_t *rpa_mnode_create(
+       rpa_match_t *match, 
+       unsigned int flags);
+rpa_mnode_t *rpa_mnode_callback_create(
+       rpa_match_t *match, 
+       unsigned int flags, 
+       RPA_MATCH_CALLBACK matched_callback, 
+       void *userdata);
+rpa_mnode_t *rpa_mnode_callback_arg1_create(
+       rpa_match_t *match, 
+       unsigned int flags, 
+       RPA_MATCH_CALLBACK matched_callback, 
+       void *userdata,
+       rpa_word_t arg1);
+rpa_mnode_t *rpa_mnode_callback_arg2_create(
+       rpa_match_t *match, 
+       unsigned int flags, 
+       RPA_MATCH_CALLBACK matched_callback, 
+       void *userdata,
+       rpa_word_t arg1,
+       rpa_word_t arg2);
+       
+rpa_mnode_t *rpa_mnode_init(
+       rpa_mnode_t *node,
+       rpa_match_t *match, 
+       unsigned int flags,
+       rpa_class_methods_t *vptr);
+rpa_mnode_t *rpa_mnode_callback_init(
+       rpa_mnode_callback_t *mnode,
+       rpa_match_t *match, 
+       unsigned int flags, 
+       RPA_MATCH_CALLBACK matched_callback, 
+       void *userdata,
+       rpa_class_methods_t *vptr);     
+int rpa_mnode_exec_callback(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason);
+int rpa_mnode_print(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason);
+int rpa_mnode_debug_print(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason);
+int rpa_mnode_check_for_loop(rpa_mnode_t *mnode, rpa_match_t *loop, rpa_head_t *mhead, int reclevel);
+
+
+int rpa_mnode_plain(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_multiple(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_optional(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_multiopt(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+
+int rpa_mnode_nlist_plain(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_nlist_multiple(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_nlist_optional(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_nlist_multiopt(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+
+
+int rpa_mnode_callback_plain(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_callback_multiple(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_callback_optional(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_callback_multiopt(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+
+int rpa_mnode_callback_loop_plain(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_callback_loop_multiple(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_callback_loop_optional(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_callback_loop_multiopt(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+
+
+/* Parser functionality */
+int rpa_mnode_p_plain(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_p_multiple(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_p_optional(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_p_multiopt(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+
+int rpa_mnode_p_callback_plain(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_p_callback_multiple(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_p_callback_optional(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_p_callback_multiopt(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+
+int rpa_mnode_p_callback_loop_plain(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_p_callback_loop_multiple(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_p_callback_loop_optional(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+int rpa_mnode_p_callback_loop_multiopt(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input);
+
+
+void rpa_mnode_cat_list(rpa_head_t *head, rpa_mnode_t *first, ...);
+rpa_mnode_t *rpa_mnode_list_append(rpa_head_t *head, rpa_mnode_t *node);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/rpa/rpaparser.c b/rpa/rpaparser.c
new file mode 100644 (file)
index 0000000..0118174
--- /dev/null
@@ -0,0 +1,2158 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#include "rpamem.h"
+#include "rpavar.h"
+#include "rpastring.h"
+#include "rpavarlink.h"
+#include "rpaparser.h"
+#include "rpamnode.h"
+#include "rpamatchstr.h"
+#include "rpamatchspecial.h"
+#include "rpamatchlist.h"
+#include "rpamatchval.h"
+#include "rpamatchrange.h"
+#include "rpadbexpriv.h"
+#include "rpadebug.h"
+
+/*
+ * Rules:
+ * 
+ * R[0] - name, matchptr
+ * R[1] - size
+ * R[2] - count
+ * R[5] - val, match function
+ * R[6] - val
+ * R[7] - current match (list)
+ * R[8] - current mnode
+ * R[11] - mnode flags
+ * 
+ * during reason 'start'the current match is saved on the stack and the newly created match is saved in R[8]
+ * during reason 'end' the match is assigned to the current mnode and the previous match is restored from the stack
+ */ 
+
+#define RPA_MATCH_NEWLINE_CLASSID      (('\0' << 24) | ('n' << 16) | ('l' << 8) | ('n' << 0))
+#define RPA_MATCH_LASTCHR_CLASSID      (('\0' << 24) | ('c' << 16) | ('s' << 8) | ('l' << 0))
+#define MATCH2LIST(m) rpa_varlink_list_add_match((m), &parser->bnftree)
+#define MNODE2LIST(m) rpa_varlink_list_add_mnode((m), &parser->bnftree)
+#define RPA_VMCODE_SIZE 256
+#define RPA_VMCODE_GROW 2048
+
+static rpa_mnode_t *rpa_varlink_list_add_mnode(rpa_mnode_t *mnode, rpa_head_t *head);
+static rpa_match_t *rpa_varlink_list_add_match(rpa_match_t *match, rpa_head_t *head);
+
+int rpa_parser_check_space(rpa_parser_t *parser)
+{
+       rpa_asmins_t *vmcode;
+       rpa_word_t vmcode_size;
+
+       if (parser->vmcode_size - parser->vmcode_off < RPA_VMCODE_GROW) {
+               vmcode_size = parser->vmcode_size + RPA_VMCODE_GROW;
+               vmcode = (rpa_asmins_t *)rpa_realloc(parser->vmcode, (unsigned long)(sizeof(rpa_asmins_t) * vmcode_size));
+               if (!vmcode)
+                       return -1;
+               parser->vmcode_size = vmcode_size;
+               parser->vmcode = vmcode;
+       }
+       return 0;
+}
+
+
+rpa_parser_t *rpa_parser_create()
+{
+       rpa_parser_t *parser;
+
+       parser = (rpa_parser_t *)rpa_malloc(sizeof(*parser));
+       if (!parser)
+               return ((void*)0);
+       rpa_memset(parser, 0, sizeof(*parser));
+       rpa_list_init(&parser->bnftree);
+       rpa_stat_init(&parser->stat);
+       rpa_stat_set_encoding(&parser->stat, RPA_ENCODING_UTF8);
+       rpa_parser_setup_bnftree(parser);
+       parser->stack = rpa_wordstack_create(256, 16);
+       if (!parser->stack)
+               goto error;
+       parser->vmcode_size = RPA_VMCODE_SIZE;
+       parser->vmcode_off = 0;
+       parser->vmcode = (rpa_asmins_t *)rpa_malloc((unsigned long)(sizeof(rpa_asmins_t) * parser->vmcode_size));
+       if (!parser->vmcode)
+               goto error;
+       return parser;
+       
+error:
+       rpa_parser_destroy(parser);
+       return (void*)0;
+}
+
+
+void rpa_parser_destroy(rpa_parser_t *parser)
+{
+       rpa_varlink_destroy_all(&parser->bnftree);
+       rpa_free(parser->vmcode);
+       if (parser->stack)
+               rpa_wordstack_destroy(parser->stack);
+       rpa_stat_cleanup(&parser->stat);
+       rpa_free(parser);
+}
+
+
+int rpa_parser_exec(rpa_parser_t *parser, const char *input, unsigned long size)
+{
+       int ret = 0;
+
+       if (parser->pVarLinkBnfRoot)
+               ret = rpa_stat_match_lite(&parser->stat, parser->pVarLinkBnfRoot, input, input, input + size);
+       return ret;
+}
+
+int rpa_parser_mnode_print(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+#ifdef CODEGENDEBUG
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;        
+       fprintf(stdout, "%5lu: ", parser->vmcode_off);
+#endif
+
+       rpa_mnode_debug_print(mnode, stat, input, size, reason);
+       return size;
+}
+
+
+int rpa_parser_mnode_print_dump_code(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason, rpa_word_t codepos)
+{
+
+#ifdef CODEGENDEBUG
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;        
+       fprintf(stdout, "%5lu: ", codepos);
+       rpa_mnode_print(mnode, stat, input, size, reason);
+       if (parser->vmcode_off > codepos)
+               rpa_asm_dump(&parser->vmcode[codepos], parser->vmcode_off - codepos);
+#else
+       rpa_mnode_debug_print(mnode, stat, input, size, reason);
+#endif
+       return size;
+}
+
+
+void rpa_parser_gencode_str_start(rpa_parser_t *parser, const char *input, unsigned int size)
+{
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, DA, XX, (rpa_word_t)0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R2, DA, XX, (rpa_word_t)0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R4, DA, XX, (rpa_word_t)0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R5, DA, XX, (rpa_word_t)0);
+}
+
+
+void rpa_parser_gencode_str_end(rpa_parser_t *parser, const char *input, unsigned int size)
+{
+       /*
+        * Save the current match ptr on the stack
+        */
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, DA, XX, (rpa_word_t)input);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)size);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R2, R4, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_STR_MATCHPTR);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R6, R0, XX, 0);
+
+       /*
+        * Pop all values off the stack
+        */
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_CMP, R4, DA, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_BLEQ, DA, XX, XX, 8);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_POP, R1, XX, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R2, R4, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_SUB, R2, R2, DA, 1);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R6, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_SET_STRVAL);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_SUB, R4, R4, DA, 1);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_B, DA, XX, XX, -8);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, DA, XX, 0);
+
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_PUSH, R7, XX, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R7, R6, XX, 0);
+       
+       
+}
+
+
+void rpa_parser_gencode_list_start(rpa_parser_t *parser, const char *input, unsigned int size, rpa_word_t lmf)
+{
+       /*
+        * Save the current list on the stack
+        */
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_PUSH, R7, XX, XX, 0);
+       
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, DA, XX, (rpa_word_t)0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R2, DA, XX, (rpa_word_t)lmf);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_LIST_MATCHPTR);
+       
+       /*
+        * Set the newly created list to be the current
+        */
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R7, R0, XX, 0);
+}
+
+
+void rpa_parser_gencode_rangelist_start(rpa_parser_t *parser, const char *input, unsigned int size)
+{
+       /*
+        * Save the current list on the stack
+        */
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_PUSH, R7, XX, XX, 0);
+       
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, DA, XX, (rpa_word_t)0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_RANGELIST_MATCHPTR);
+       
+       /*
+        * Set the newly created list to be the current
+        */
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R7, R0, XX, 0);
+}
+
+
+void rpa_parser_gencode_list_end(rpa_parser_t *parser, const char *input, unsigned int size)
+{
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)input);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R2, DA, XX, (rpa_word_t)size);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_SET_MATCH_NAME);
+
+}
+
+#if 0
+void rpa_parser_gencode_nlist_start(rpa_parser_t *parser, const char *input, unsigned int size, rpa_word_t lmf)
+{
+       /*
+        * Save the current list on the stack
+        */
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_PUSH, R7, XX, XX, 0);
+       
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, DA, XX, (rpa_word_t)0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R2, DA, XX, (rpa_word_t)lmf);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_NLIST_MATCHPTR);
+       
+       /*
+        * Set the newly created list to be the current
+        */
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R7, R0, XX, 0);
+       
+}
+#endif
+
+void rpa_parser_gencode_nlist_end(rpa_parser_t *parser, const char *input, unsigned int size)
+{
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)input);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R2, DA, XX, (rpa_word_t)size);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_SET_MATCH_NAME);
+
+}
+
+
+void rpa_parser_gencode_hlist_start(rpa_parser_t *parser, const char *input, unsigned int size, rpa_word_t lmf)
+{
+       /*
+        * Save the current list on the stack
+        */
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_PUSH, R7, XX, XX, 0);
+       
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, DA, XX, (rpa_word_t)0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R2, DA, XX, (rpa_word_t)lmf);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_HLIST_MATCHPTR);
+       
+       /*
+        * Set the newly created list to be the current
+        */
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R7, R0, XX, 0);
+}
+
+
+void rpa_parser_gencode_hlist_end(rpa_parser_t *parser, const char *input, unsigned int size)
+{
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)input);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R2, DA, XX, (rpa_word_t)size);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_SET_MATCH_NAME);
+
+}
+
+
+void rpa_parser_gencode_set_matchfunc(rpa_parser_t *parser, const char *input, unsigned int size, rpa_word_t lmf)
+{
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)lmf);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_SET_MATCH_FUNCTION);
+
+}
+
+
+void rpa_parser_gencode_nlist_set_matchfunc(rpa_parser_t *parser, const char *input, unsigned int size, rpa_word_t lmf)
+{
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_GET_MATCH_FUNCTION);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_CMP, R0, DA, XX, lmf);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_BEQ, DA, XX, XX, 3);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_RESET_LIST);
+
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_CMP, R0, DA, XX, RPA_MATCHFUNC_LIST);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_BNEQ, DA, XX, XX, 3);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_RESET_LIST);
+
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)lmf);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_SET_MATCH_FUNCTION);
+
+}
+
+
+void rpa_parser_gencode_setup_list(rpa_parser_t *parser)
+{
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_SETUP_LIST);
+
+}
+
+
+void rpa_parser_gencode_nlist_get(rpa_parser_t *parser, const char *input, unsigned int size)
+{
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, DA, XX, (rpa_word_t)input);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)size);
+       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_GET_NLIST_MATCHPTR);
+}
+
+
+int rpa_parser_cb_assign(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       if (rpa_strncmp(input, "::=", size) == 0)
+                               rpa_parser_gencode_nlist_set_matchfunc(parser, input, size, RPA_MATCHFUNC_LIST);
+                       else if (rpa_strncmp(input, "++=", size) == 0)
+                               rpa_parser_gencode_nlist_set_matchfunc(parser, input, size, RPA_MATCHFUNC_NLIST_BESTALT);
+                       else if (rpa_strncmp(input, "||=", size) == 0)
+                               rpa_parser_gencode_nlist_set_matchfunc(parser, input, size, RPA_MATCHFUNC_NLIST_ALT);
+                       else
+                               rpa_parser_gencode_nlist_set_matchfunc(parser, input, size, RPA_MATCHFUNC_LIST);
+                       break;
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+       }       
+       
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_opsign(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+       rpa_word_t lmf;
+       
+       switch (reason) {
+               case RPA_REASON_START:
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       switch (*input) {
+                               case '^': 
+                                       lmf = RPA_MATCHFUNC_LIST_NOT;
+                                       break;
+                               case '|': 
+                                       lmf = RPA_MATCHFUNC_LIST_ALT;                           
+                                       break;
+                               case '&': 
+                                       lmf = RPA_MATCHFUNC_LIST_AND;
+                                       break;
+                               case '-': 
+                                       lmf = RPA_MATCHFUNC_LIST_MINUS;
+                                       break;
+                               case '%': 
+                                       lmf = RPA_MATCHFUNC_LIST_CONTAIN;
+                                       break;
+                               case '@': 
+                                       lmf = RPA_MATCHFUNC_LIST_AT;
+                                       break;
+                               default:
+                                       lmf = RPA_MATCHFUNC_LIST;
+                                       break;
+                       }
+                       rpa_parser_gencode_set_matchfunc(parser, input, size, lmf);
+                       break;
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+       }       
+       
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_newline_matchptr(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       /*
+                        * Save the current match ptr on the stack
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_PUSH, R7, XX, XX, 0);
+
+                       /*
+                        * Create a new val matchptr and set it in R7 to be the current one
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, DA, XX, (rpa_word_t)input);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)size);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_NEWLINE_MATCHPTR);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R7, R0, XX, 0);
+                       break;
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+       }       
+       
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+                               
+       return size;
+}
+
+
+int rpa_parser_cb_anychar_matchptr(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       /*
+                        * Save the current match ptr on the stack
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_PUSH, R7, XX, XX, 0);
+
+                       /*
+                        * Create a new val matchptr and set it in R7 to be the current one
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, DA, XX, (rpa_word_t)input);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)size);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_ANYCHAR_MATCHPTR);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R7, R0, XX, 0);
+                       break;
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+       }       
+       
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+                               
+       return size;
+}
+
+
+int rpa_parser_cb_fun_matchptr(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t excall = ((rpa_mnode_callback_arg1_t*)mnode)->arg1;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       /*
+                        * Save the current match ptr on the stack
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_PUSH, R7, XX, XX, 0);
+
+                       /*
+                        * Create a new val matchptr and set it in R7 to be the current one
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, DA, XX, (rpa_word_t)input);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)size);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, excall);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R7, R0, XX, 0);
+                       break;
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+       }       
+       
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+                               
+       return size;
+}
+
+
+int rpa_parser_cb_val_matchptr(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       /*
+                        * Save the current match ptr on the stack
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_PUSH, R7, XX, XX, 0);
+
+                       /*
+                        * Create a new val matchptr and set it in R7 to be the current one
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, DA, XX, (rpa_word_t)input);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)size);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R2, R5, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_VAL_MATCHPTR);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R7, R0, XX, 0);
+                       break;
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+       }       
+       
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+                               
+       return size;
+}
+
+
+int rpa_parser_cb_hexnum_r5(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       unsigned int wc = 0;
+       char *endptr = (void*)0;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       wc = rpa_strtoul(input, &endptr, 16);
+       
+       switch (reason) {
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       rpa_parser_check_space(parser);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R5, DA, XX, (rpa_word_t)wc);
+                       break;
+               default:
+                       break;
+       }
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_hexnum_r6(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       unsigned int wc = 0;
+       char *endptr = (void*)0;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       wc = rpa_strtoul(input, &endptr, 16);
+       
+       switch (reason) {
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       rpa_parser_check_space(parser);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R6, DA, XX, (rpa_word_t)wc);
+                       break;
+               default:
+                       break;
+       }
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_decnum_r5(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       unsigned int wc = 0;
+       char *endptr = (void*)0;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       wc = rpa_strtoul(input, &endptr, 10);
+       
+       switch (reason) {
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       rpa_parser_check_space(parser);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R5, DA, XX, (rpa_word_t)wc);
+                       break;
+               default:
+                       break;
+       }
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_decnum_r6(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       unsigned int wc = 0;
+       char *endptr = (void*)0;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       wc = rpa_strtoul(input, &endptr, 10);
+       
+       switch (reason) {
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       rpa_parser_check_space(parser);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R6, DA, XX, (rpa_word_t)wc);
+                       break;
+               default:
+                       break;
+       }
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_val_r5(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       unsigned int wc = 0;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       if (rpa_utf8_mbtowc(&wc, (const unsigned char*)input, (const unsigned char*)(input + size)) < 0) {
+               wc = *input;
+       }
+       switch (reason) {
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       rpa_parser_check_space(parser);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R5, DA, XX, (rpa_word_t)wc);
+                       break;
+               default:
+                       break;
+       }
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_push_r5_inc_r4(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       unsigned int wc = 0;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       if (rpa_utf8_mbtowc(&wc, (const unsigned char*)input, (const unsigned char*)(input + size)) < 0) {
+               wc = *input;
+       }
+       switch (reason) {
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       rpa_parser_check_space(parser);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_PUSH, R5, XX, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_ADD, R4, R4, DA, 1);
+                       break;
+               default:
+                       break;
+       }
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_esc_val_r5(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       unsigned int wc = 0;
+       const char *chInput = input;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       if (*chInput == '\\') {
+                               ++chInput;
+                               if (rpa_utf8_mbtowc(&wc, (const unsigned char*)chInput, (const unsigned char*)(input + size)) < 0)
+                                       wc = *input;
+                               switch (wc) {
+                               case 'n':
+                                       wc = '\n';
+                                       break;
+                               case 'r':
+                                       wc = '\r';
+                                       break;
+                               case 't':
+                                       wc = '\t';
+                                       break;
+                               case '\'':
+                                       wc = '\'';
+                                               break;
+                               case '\"':
+                                       wc = '\"';
+                                       break;
+                               case '\\':
+                                       wc = '\\';
+                                       break;
+                               }       
+                       }
+                       rpa_parser_check_space(parser);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R5, DA, XX, (rpa_word_t)wc);
+                       break;
+               default:
+                       break;
+       }
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_val_r6(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       unsigned int wc = 0;
+       rpa_word_t codepos = parser->vmcode_off;
+       
+       if (rpa_utf8_mbtowc(&wc, (const unsigned char*)input, (const unsigned char*)(input + size)) < 0) {
+               wc = *input;
+       }
+       switch (reason) {
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       rpa_parser_check_space(parser);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R6, DA, XX, (rpa_word_t)wc);
+                       break;
+                       break;
+               default:
+                       break;
+       }                       
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_range_matchptr(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       /*
+                        * Save the current match ptr on the stack
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_PUSH, R7, XX, XX, 0);
+
+                       /*
+                        * Create a new val matchptr and set it in R7 to be the current one
+                        */             
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, DA, XX, (rpa_word_t)input);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, (rpa_word_t)size);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R2, R5, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R3, R6, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_RANGE_MATCHPTR);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R7, R0, XX, 0);
+                       break;
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+       }
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_mnodeptr_in_nlist(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_MNODE);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R10, R0, XX, 0);        // save the mnode in R10
+
+
+                       /*
+                        * Add the mnode to the current list
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, R0, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_POP, R7, XX, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_ADD_MNODE_TO_LIST);
+                       
+                       /*
+                        * Add the mnode to the hash
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, R10, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_ADD_MNODE_TO_LIST_DATAPTR);
+                       
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+               };
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_mnodeptr_in_altlist(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R10, R7, XX, 0);        // save current match in R10
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_MNODE);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R9, R0, XX, 0);         // save the newly created mnode in R9
+
+                       /*
+                        * Add the mnode to the current list
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, R0, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_POP, R7, XX, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_ADD_MNODE_TO_LIST);
+                       
+                       /*
+                        * Add the mnode to the hash
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, R9, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_ADD_MNODE_TO_LIST_DATAPTR);
+
+                       
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+               };
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_mnodeptr(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, DA, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_MNODE);
+
+                       /*
+                        * Add the mnode to the current list
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, R0, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_POP, R7, XX, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_ADD_MNODE_TO_LIST);                     
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+               };
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_q_mnodeptr(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R11, DA, XX, 0);
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, R11, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_MNODE);
+
+                       /*
+                        * Add the mnode to the current list
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, R0, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_POP, R7, XX, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_ADD_MNODE_TO_LIST);                     
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+               };
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+static int rpa_parser_acb_q_mnodeptr_callback(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R11, DA, XX, 0);
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, R11, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_ORR, R1, R1, DA, RPA_MNODE_CALLBACK);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_MNODE_CALLBACK);
+
+                       /*
+                        * Add the mnode to the current list
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, R0, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_POP, R7, XX, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_ADD_MNODE_TO_LIST);                     
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+               };
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+static int rpa_parser_scb_q_mnodeptr_callback(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R11, DA, XX, 0);
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, R11, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_ORR, R1, R1, DA, RPA_MNODE_CALLBACK | RPA_MNODE_SYNCRONOUS);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_MNODE_CALLBACK);
+
+                       /*
+                        * Add the mnode to the current list
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, R0, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_POP, R7, XX, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_ADD_MNODE_TO_LIST);                     
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+               };
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+static int rpa_parser_ncb_q_mnodeptr_callback(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R11, DA, XX, 0);
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, R11, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_ORR, R1, R1, DA, RPA_MNODE_CALLBACK | RPA_MNODE_NOCONNECT);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_CREATE_MNODE_CALLBACK);
+
+                       /*
+                        * Add the mnode to the current list
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R1, R0, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_POP, R7, XX, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0); 
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_ADD_MNODE_TO_LIST);                     
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+               };
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_quantity(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_word_t flags = 0;
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       if (size) {
+               switch (*input) {
+               case '*':
+                       flags = RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE;
+                       break;
+               case '+':
+                       flags = RPA_MATCH_MULTIPLE;
+                       break;
+               case '?':
+                       flags = RPA_MATCH_OPTIONAL;
+                       break;
+               default:
+                       flags = 0;
+                       break;
+               }
+       }
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R11, DA, XX, 0);
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R11, DA, XX, flags);
+                       break;
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;
+       }
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+int rpa_parser_cb_class(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+       
+       switch (reason) {
+               case RPA_REASON_START:
+                       rpa_parser_check_space(parser);
+                       rpa_wordstack_check_space(parser->stack);
+                       rpa_wordstack_push(parser->stack, parser->vmcode_off);
+                       rpa_parser_gencode_rangelist_start(parser, input, size);
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:                        
+                       rpa_parser_gencode_list_end(parser, input, size);
+                       rpa_parser_gencode_setup_list(parser);
+                       rpa_wordstack_pop(parser->stack);               
+                       break;
+               case RPA_REASON_END:
+                       parser->vmcode_off = rpa_wordstack_pop(parser->stack);          
+                       break;
+               default:
+                       break;
+       }
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_seqexpr(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       rpa_parser_check_space(parser);
+                       rpa_wordstack_check_space(parser->stack);
+                       rpa_wordstack_push(parser->stack, parser->vmcode_off);
+                       rpa_parser_gencode_list_start(parser, input, size, RPA_MATCHFUNC_LIST);
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:                        
+                       rpa_parser_gencode_list_end(parser, input, size);
+                       rpa_parser_gencode_setup_list(parser);
+                       rpa_wordstack_pop(parser->stack);               
+                       break;
+               case RPA_REASON_END:
+                       parser->vmcode_off = rpa_wordstack_pop(parser->stack);          
+                       break;
+               default:
+                       break;
+       }
+
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_strexpr(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       rpa_parser_check_space(parser);
+                       rpa_wordstack_check_space(parser->stack);
+                       rpa_wordstack_push(parser->stack, parser->vmcode_off);
+                       rpa_parser_gencode_str_start(parser, input, size);
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:                        
+                       rpa_parser_gencode_str_end(parser, input, size);
+                       rpa_wordstack_pop(parser->stack);
+                       break;
+               case RPA_REASON_END:
+                       parser->vmcode_off = rpa_wordstack_pop(parser->stack);          
+                       break;
+               default:
+                       break;
+       }
+
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_altexpr(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       rpa_parser_check_space(parser);
+                       rpa_wordstack_check_space(parser->stack);
+                       rpa_wordstack_push(parser->stack, parser->vmcode_off);
+                       rpa_parser_gencode_list_start(parser, input, size, RPA_MATCHFUNC_LIST_ALT);
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:                        
+                       rpa_parser_gencode_list_end(parser, input, size);
+                       rpa_parser_gencode_setup_list(parser);
+                       rpa_wordstack_pop(parser->stack);               
+                       break;
+               case RPA_REASON_END:
+                       parser->vmcode_off = rpa_wordstack_pop(parser->stack);          
+                       break;
+               default:
+                       break;
+       }
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_namedexpr(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+
+       switch (reason) {
+               case RPA_REASON_START:
+                       rpa_parser_check_space(parser);
+                       rpa_wordstack_check_space(parser->stack);
+                       rpa_wordstack_push(parser->stack, parser->vmcode_off);
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       rpa_parser_gencode_setup_list(parser);                  
+                       rpa_wordstack_pop(parser->stack);               
+                       break;
+               case RPA_REASON_END:
+                       parser->vmcode_off = rpa_wordstack_pop(parser->stack);          
+                       break;
+               default:
+                       break;
+       }
+
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+
+int rpa_parser_cb_codeboundary(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+       
+       switch (reason) {
+               case RPA_REASON_START:
+                       rpa_wordstack_check_space(parser->stack);
+                       rpa_wordstack_push(parser->stack, parser->vmcode_off);
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       rpa_wordstack_pop(parser->stack);               
+                       break;
+               case RPA_REASON_END:
+                       parser->vmcode_off = rpa_wordstack_pop(parser->stack);          
+                       break;
+               default:
+                       break;
+       }
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_nlist(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+       
+       switch (reason) {
+               case RPA_REASON_START:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_PUSH, R7, XX, XX, 0);
+                       break;  
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       rpa_parser_gencode_nlist_get(parser, input, size);
+                       /*
+                        * The hlist match ptr will be in r[0]
+                        * Make this the current match now
+                        */
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R7, R0, XX, 0);
+                       
+                       break;
+               case RPA_REASON_END:
+                       break;
+               default:
+                       break;                  
+       }
+       
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+int rpa_parser_cb_rpaexpr(rpa_mnode_t *mnode, rpa_stat_t *stat, const char *input, unsigned int size, unsigned int reason)
+{
+       rpa_parser_t *parser = (rpa_parser_t*) ((rpa_mnode_callback_t*)mnode)->userdata;
+       rpa_word_t codepos = parser->vmcode_off;
+       
+       switch (reason) {
+               case RPA_REASON_START:
+                       parser->vmcode_off = 0;
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, SP, DA, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R7, DA, XX, 0);
+                       break;
+               case RPA_REASON_END|RPA_REASON_MATCHED:
+               case RPA_REASON_MATCHED:
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_CMP, R7, DA, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_BEQ, DA, XX, XX, 3);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_SET_DEFAULT_PATTERN);
+                       
+#if 0                  
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_MOV, R0, R7, XX, 0);
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_XCAL, DA, XX, XX, VM_DUMP_TREE);
+#endif
+                       parser->vmcode[parser->vmcode_off++] = rpa_asm(RPA_EXT, R0, XX, XX, 0);
+
+                       break;
+               case RPA_REASON_END:
+                       parser->vmcode_off = 0; 
+                       break;
+               default:
+                       break;
+       }
+
+       rpa_parser_mnode_print_dump_code(mnode, stat, input, size, reason, codepos);
+       return size;
+}
+
+
+rpa_match_t *rpa_parser_list_from_str(rpa_parser_t *parser, const char *name, rpa_matchfunc_t match_function_id, const char *str)
+{
+       rpa_match_val_t *val;
+       rpa_mnode_t *mnode;
+       rpa_match_list_t *list = (rpa_match_list_t*) rpa_match_list_create(name, match_function_id);
+       
+       while (str && *str) {
+               val = (rpa_match_val_t *)MATCH2LIST(rpa_match_val_create_namesize(str, 1, RPA_MATCHFUNC_VAL_CHREQ, *str));
+               mnode = MNODE2LIST(rpa_mnode_callback_create(&val->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser));
+               rpa_list_addt(&list->head, &mnode->mlink);
+               str += 1;
+       }
+       return (rpa_match_t*)list;
+}
+
+
+void rpa_parser_setup_bnftree(rpa_parser_t *parser)
+{
+       rpa_match_list_t *notExpressionOperand = NULL, *notExpression = NULL, *notExpressionMatch = NULL;
+       rpa_match_list_t *embeddedExprMnodeScb = NULL, *embeddedExprMnodeAcb = NULL, *embeddedExprMnodeNcb = NULL;
+       rpa_match_list_t *qMnode = NULL, *paddedQMnodeNcb = NULL, *paddedQMnodeAcb = NULL, *paddedQMnodeScb = NULL, *paddedQMnode = NULL, *qMnodeExpr = NULL, *simpMnode = NULL, *rpaExpr = NULL;
+       rpa_match_list_t *exprMnode = NULL, *exprMnodeInNList = NULL, *exprMatch = NULL, *expr = NULL, *opOrSeqExprMatch = NULL, *opOrSeqExprMnode = NULL, *opOrSeqExpr = NULL;
+       rpa_match_list_t *seqExpr = NULL, *seqExprMatch = NULL, *seqExprMnode = NULL, *eoe = NULL;
+       rpa_match_list_t *altExprStartMember = NULL, *altExprEndMember = NULL, *opExprAlt = NULL, *opExpr = NULL, *opsign = NULL, *spOpsign = NULL, *spOrSign = NULL;
+       rpa_match_list_t *embeddedExprNcb = NULL, *embeddedExprAcb = NULL, *embeddedExprScb = NULL;
+       rpa_match_list_t *bracketExpr = NULL, *bracketExprMatch = NULL;
+       rpa_match_list_t *namedExpr = NULL, *namedExprReg = NULL, *namedExprOrr = NULL, *namedExprBest = NULL, *namedExprMatch = NULL;
+       rpa_match_list_t *exprName = NULL, *exprNameMatch = NULL, *prettyAssign = NULL, *prettyBest = NULL, *prettyOrr = NULL;
+       rpa_match_list_t *comment = NULL, *spaceOrLf = NULL, *ignoreLine = NULL;
+       rpa_match_list_t *alpha = NULL, *alphanum = NULL, *nsalphanum = NULL, *range = NULL, *ignore = NULL, *rangeMatch = NULL, *classMember = NULL, *classExpr = NULL, *classExprMatch = NULL;
+       rpa_match_list_t *numClassMatch = NULL, *numClassDecimal_r5 = NULL, *numClassHex_r5 = NULL, *numClassNumberMatch_r5 = NULL, *numClassDecimal_r6 = NULL, *numClassHex_r6 = NULL, *numClassNumberMatch_r6 = NULL;
+       rpa_match_list_t *numClassRange = NULL, *numClassSingle = NULL;
+       rpa_match_list_t *notDblQuote = NULL, *notSnglQuote = NULL, *notDblQuoteMatch = NULL, *notSnglQuoteMatch = NULL, *notDblQuoteVal = NULL, *notSnglQuoteVal = NULL;
+       rpa_match_list_t *spRegExprCh = NULL, *escCh = NULL, *classCh = NULL, *classChMatch = NULL, *exprCh = NULL, *exprChMatch = NULL;
+       rpa_match_list_t *exprStrDblQuote = NULL, *exprStrSnglQuote = NULL, *exprStrVal = NULL, *exprQStrMatch = NULL;
+       rpa_match_list_t *newlineMatch = NULL, *anycharMatch = NULL, *hex = NULL, *hexNum = NULL, *decNum = NULL;
+       rpa_match_list_t *prettyQuantity = NULL;
+       
+       rpa_match_range_t *lower = NULL, *upper = NULL, *digit = NULL, *loHex = NULL, *upHex = NULL;
+       rpa_match_val_t *pound = NULL, *lf = NULL, *cr = NULL, *notlf = NULL, *eos = NULL;
+       rpa_match_val_t *underscore = NULL, *col = NULL, *semicol = NULL, *snglQuote = NULL, *dblQuote = NULL, *notquote = NULL, *or = NULL;
+       rpa_match_val_t *and = NULL, *contain = NULL, *minus = NULL, *notSign = NULL, *dash = NULL, *zero = NULL, *dot = NULL, *at = NULL;
+       rpa_match_val_t *bracketOpen = NULL, *bracketClose = NULL, *squareOpen = NULL, *squareClose = NULL, *backslash = NULL, *newline = NULL;
+       rpa_match_val_t *curlyOpen = NULL, *curlyClose = NULL;
+       rpa_match_list_t  *oname_ncb = NULL, *cname_ncb = NULL, *oname_acb = NULL, *cname_acb = NULL, *oname_scb = NULL, *cname_scb = NULL;
+       rpa_match_list_t *exprDblQuoteStr = NULL, *exprDblQuoteStrMatch = NULL, *exprSnglQuoteStr = NULL, *exprSnglQuoteStrMatch = NULL, *regExprCh = NULL;
+       
+       rpa_match_list_t *x = NULL, *quantity = NULL, *crlf = NULL;
+       rpa_match_list_t *assign = NULL, *best = NULL, *orr = NULL, *space = NULL;
+       rpa_match_list_t *regClassCh = NULL, *nseparator = NULL;
+       rpa_match_list_t *funFail = NULL, *funAbort = NULL, *funLast = NULL, *funMemberMatch;
+       rpa_match_list_t *fnFail = NULL, *fnAbort = NULL, *fnLast = NULL;
+       rpa_match_t *lastCh = NULL, *anychar = NULL;
+       rpa_match_t *root;
+       rpa_varlink_t *pVarLinkRoot;
+       
+       quantity = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "quantity", RPA_MATCHFUNC_LIST_ALT, "*+?"));
+       assign = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "assign", RPA_MATCHFUNC_LIST, "::="));
+       best = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "best", RPA_MATCHFUNC_LIST, "++="));
+       orr = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "orr", RPA_MATCHFUNC_LIST, "||="));
+       oname_ncb = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "oname_ncb", RPA_MATCHFUNC_LIST, "<"));
+       cname_ncb = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "cname_ncb", RPA_MATCHFUNC_LIST, ">"));
+       oname_acb = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "oname_acb", RPA_MATCHFUNC_LIST, "<:"));
+       cname_acb = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "cname_acb", RPA_MATCHFUNC_LIST, ":>"));
+       oname_scb = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "oname_scb", RPA_MATCHFUNC_LIST, "<;"));
+       cname_scb = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "cname_scb", RPA_MATCHFUNC_LIST, ";>"));
+       
+       fnFail = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "fnFail", RPA_MATCHFUNC_LIST, "fail"));
+       fnAbort = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "fnAbort", RPA_MATCHFUNC_LIST, "abort"));
+       fnLast = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "fnLast", RPA_MATCHFUNC_LIST, "last"));
+       regExprCh = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "regExprCh", RPA_MATCHFUNC_LIST_NOALT, " :#@^-|&%+*?\"\'[](){}<>;\n\r\0"));
+       regClassCh = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "regClassCh", RPA_MATCHFUNC_LIST_NOALT, "\\-[]\n\r\0"));
+       space = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "space", RPA_MATCHFUNC_LIST_ALT, " \t"));
+       x = (rpa_match_list_t*) MATCH2LIST(rpa_parser_list_from_str(parser, "x", RPA_MATCHFUNC_LIST_ALT, "xX"));
+
+       lastCh = MATCH2LIST(rpa_match_create("lastCh", RPA_MATCHFUNC_LSTCHR));
+       lower = (rpa_match_range_t*) MATCH2LIST(rpa_match_range_create("lower", RPA_MATCHFUNC_RANGE_CHRINRANGE, 'a', 'z'));
+       upper = (rpa_match_range_t*) MATCH2LIST(rpa_match_range_create("upper", RPA_MATCHFUNC_RANGE_CHRINRANGE, 'A', 'Z'));
+       loHex = (rpa_match_range_t*) MATCH2LIST(rpa_match_range_create("loHex", RPA_MATCHFUNC_RANGE_CHRINRANGE, 'a', 'f'));
+       upHex = (rpa_match_range_t*) MATCH2LIST(rpa_match_range_create("upHex", RPA_MATCHFUNC_RANGE_CHRINRANGE, 'A', 'F'));
+       digit = (rpa_match_range_t*) MATCH2LIST(rpa_match_range_create("digit", RPA_MATCHFUNC_RANGE_CHRINRANGE, '0', '9'));
+       
+       semicol = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("semicol", RPA_MATCHFUNC_VAL_CHREQ, ';'));
+       underscore = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("undersocre", RPA_MATCHFUNC_VAL_CHREQ, '_'));
+       backslash = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("backslash", RPA_MATCHFUNC_VAL_CHREQ, '\\'));
+       anychar = (rpa_match_t*) MATCH2LIST(rpa_match_special_create("anychar", RPA_MATCHFUNC_CHREQANY));
+       dblQuote = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("dblQuote", RPA_MATCHFUNC_VAL_CHREQ, '"'));
+       snglQuote = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("snglQuote", RPA_MATCHFUNC_VAL_CHREQ, '\''));    
+       notquote = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("notquote", RPA_MATCHFUNC_VAL_CHRNOTEQ, '"'));            
+       at = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("at", RPA_MATCHFUNC_VAL_CHREQ, '@'));
+       or = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("or", RPA_MATCHFUNC_VAL_CHREQ, '|'));
+       and = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("and", RPA_MATCHFUNC_VAL_CHREQ, '&'));
+       contain = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("contain", RPA_MATCHFUNC_VAL_CHREQ, '%'));
+       minus = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("minus", RPA_MATCHFUNC_VAL_CHREQ, '-'));
+       notSign= (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("notSign", RPA_MATCHFUNC_VAL_CHREQ, '^'));
+       col = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("col", RPA_MATCHFUNC_VAL_CHREQ, ':'));
+       dash = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("dash", RPA_MATCHFUNC_VAL_CHREQ, '-'));
+       dot = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("dot", RPA_MATCHFUNC_VAL_CHREQ, '.')); 
+       newline = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("newline", RPA_MATCHFUNC_VAL_CHREQ, '~'));
+       bracketOpen = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("bracketopen", RPA_MATCHFUNC_VAL_CHREQ, '('));
+       bracketClose = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("bracketclose", RPA_MATCHFUNC_VAL_CHREQ, ')'));
+       curlyOpen = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("curlyopen", RPA_MATCHFUNC_VAL_CHREQ, '{'));
+       curlyClose = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("curlyclose", RPA_MATCHFUNC_VAL_CHREQ, '}'));
+       squareOpen = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("squareopen", RPA_MATCHFUNC_VAL_CHREQ, '['));
+       squareClose = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("squareclose", RPA_MATCHFUNC_VAL_CHREQ, ']'));
+       lf = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("lf", RPA_MATCHFUNC_VAL_CHREQ, '\n'));
+       cr = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("cr", RPA_MATCHFUNC_VAL_CHREQ, '\r'));
+       eos = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("eos", RPA_MATCHFUNC_VAL_CHREQ, '\0'));
+       
+       notlf = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("notlf", RPA_MATCHFUNC_VAL_CHRNOTEQ, '\n'));
+       pound = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("pound", RPA_MATCHFUNC_VAL_CHREQ, '#'));
+       zero = (rpa_match_val_t*) MATCH2LIST(rpa_match_val_create("zero", RPA_MATCHFUNC_VAL_CHREQ, '0'));
+
+       funFail = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("funFail", RPA_MATCHFUNC_LIST));
+       funAbort = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("funAbort", RPA_MATCHFUNC_LIST));
+       funLast = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("funLast", RPA_MATCHFUNC_LIST));
+       funMemberMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("funMemberMatch", RPA_MATCHFUNC_LIST_ALT));
+
+       prettyQuantity = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("prettyQuantity", RPA_MATCHFUNC_LIST));
+       nseparator = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("nseparator", RPA_MATCHFUNC_LIST_ALT));
+       ignoreLine = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("ignoreLine", RPA_MATCHFUNC_LIST_ALT));
+       bracketExprMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("bracketExprMatch", RPA_MATCHFUNC_LIST));
+       bracketExpr = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("bracketExpr", RPA_MATCHFUNC_LIST));
+       notExpressionOperand = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("notExpressionOperand", RPA_MATCHFUNC_LIST_ALT));   
+       notExpression = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("notExpression", RPA_MATCHFUNC_LIST));     
+       notExpressionMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("notExpressionMatch", RPA_MATCHFUNC_LIST));   
+       exprQStrMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("exprQStrMatch", RPA_MATCHFUNC_LIST_ALT));
+       expr = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("expr", RPA_MATCHFUNC_LIST_ALT));
+       opOrSeqExpr = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("opOrSeqExpr", RPA_MATCHFUNC_LIST_ALT));
+       opOrSeqExprMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("opOrSeqExprMatch", RPA_MATCHFUNC_LIST));
+       opOrSeqExprMnode = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("opOrSeqExprMnode", RPA_MATCHFUNC_LIST));
+       seqExpr = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("seqExpr", RPA_MATCHFUNC_LIST));
+       seqExprMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("seqExprMatch", RPA_MATCHFUNC_LIST_ALT));
+       seqExprMnode = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("seqExprMnode", RPA_MATCHFUNC_LIST));
+       opExpr = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("opExpr", RPA_MATCHFUNC_LIST));
+       opExprAlt = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("opExprAlt", RPA_MATCHFUNC_LIST));
+       altExprStartMember = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("altExprStartMember", RPA_MATCHFUNC_LIST));
+       altExprEndMember = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("altExprEndMember", RPA_MATCHFUNC_LIST));
+       exprStrVal = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("exprStrVal", RPA_MATCHFUNC_LIST_ALT));
+       exprStrDblQuote = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("exprStrDblQuote", RPA_MATCHFUNC_LIST));
+       exprStrSnglQuote = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("exprStrSnglQuote", RPA_MATCHFUNC_LIST));
+       notSnglQuote = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("notSnglQuote", RPA_MATCHFUNC_LIST_NOT));
+       notDblQuote = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("notDblQuote", RPA_MATCHFUNC_LIST_NOT));
+       notSnglQuoteMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("notSnglQuoteMatch", RPA_MATCHFUNC_LIST));
+       notDblQuoteMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("notDblQuoteMatch", RPA_MATCHFUNC_LIST));
+       notSnglQuoteVal = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("notSnglQuoteVal", RPA_MATCHFUNC_LIST));
+       notDblQuoteVal = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("notDblQuoteVal", RPA_MATCHFUNC_LIST));
+       qMnodeExpr = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("qMnodeExpr", RPA_MATCHFUNC_LIST_ALT));
+       paddedQMnodeNcb = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("paddedQMnodeNcb", RPA_MATCHFUNC_LIST));
+       paddedQMnodeAcb = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("paddedQMnodeNcb", RPA_MATCHFUNC_LIST));
+       paddedQMnodeScb = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("paddedQMnodeScb", RPA_MATCHFUNC_LIST));
+       paddedQMnode = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("paddedQMnode", RPA_MATCHFUNC_LIST));
+       qMnode = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("qMnode", RPA_MATCHFUNC_LIST));
+       ignore = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("ignore", RPA_MATCHFUNC_LIST));
+       simpMnode = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("simpMnode", RPA_MATCHFUNC_LIST_ALT));
+       embeddedExprMnodeAcb = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("embeddedExprMnodeAcb", RPA_MATCHFUNC_LIST));
+       embeddedExprMnodeScb = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("embeddedExprMnodeScb", RPA_MATCHFUNC_LIST));
+       embeddedExprMnodeNcb = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("embeddedExprMnodeNcb", RPA_MATCHFUNC_LIST));
+       exprChMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("exprChMatch", RPA_MATCHFUNC_LIST));
+       spOrSign = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("spOrSign", RPA_MATCHFUNC_LIST));
+       spOpsign = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("spOpsign", RPA_MATCHFUNC_LIST));
+       opsign = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("opsign", RPA_MATCHFUNC_LIST_ALT));
+       namedExprMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("namedExprMatch", RPA_MATCHFUNC_LIST));
+       namedExprReg = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("namedExprReg", RPA_MATCHFUNC_LIST));
+       namedExprOrr = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("namedExprOrr", RPA_MATCHFUNC_LIST));
+       namedExprBest = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("namedExprBest", RPA_MATCHFUNC_LIST));
+       namedExpr = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("namedExpr", RPA_MATCHFUNC_LIST_ALT));
+
+       exprMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("epxrMatch", RPA_MATCHFUNC_LIST_ALT));
+       exprMnode = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("epxrMnode", RPA_MATCHFUNC_LIST));
+       exprMnodeInNList = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("exprMnodeInNList", RPA_MATCHFUNC_LIST));
+       eoe = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("eoe", RPA_MATCHFUNC_LIST_ALT));
+       embeddedExprAcb = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("embeddedExprAcb", RPA_MATCHFUNC_LIST));
+       embeddedExprScb = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("embeddedExprScb", RPA_MATCHFUNC_LIST));
+       embeddedExprNcb = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("embeddedExprNcb", RPA_MATCHFUNC_LIST));
+       anycharMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("anycharMatch", RPA_MATCHFUNC_LIST));
+       newlineMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("newlineMatch", RPA_MATCHFUNC_LIST));
+       prettyAssign = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("prettyAssign", RPA_MATCHFUNC_LIST));
+       prettyOrr = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("prettyOrr", RPA_MATCHFUNC_LIST));
+       prettyBest = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("prettyBest", RPA_MATCHFUNC_LIST));
+       exprNameMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("exprNameMatch", RPA_MATCHFUNC_LIST));
+       exprName = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("exprName", RPA_MATCHFUNC_LIST));
+       nsalphanum = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("nsalphanum", RPA_MATCHFUNC_LIST));
+       alphanum = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("alphanum", RPA_MATCHFUNC_LIST_ALT));
+       alpha = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("alpha", RPA_MATCHFUNC_LIST_ALT));
+       numClassMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("numClassMatch", RPA_MATCHFUNC_LIST_ALT));
+       numClassSingle = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("numClassSingle", RPA_MATCHFUNC_LIST));
+       numClassRange = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("numClassRange", RPA_MATCHFUNC_LIST));
+       numClassNumberMatch_r5 = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("numClassNumberMatch_r5", RPA_MATCHFUNC_LIST_ALT));
+       numClassNumberMatch_r6 = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("numClassNumberMatch_r6", RPA_MATCHFUNC_LIST_ALT));
+       numClassHex_r5 = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("numClassHex_r5", RPA_MATCHFUNC_LIST));
+       numClassHex_r6 = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("numClassHex_r6", RPA_MATCHFUNC_LIST));
+       hex = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("hex", RPA_MATCHFUNC_LIST_ALT));
+       hexNum = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("hexNum", RPA_MATCHFUNC_LIST));
+       decNum = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("decNum", RPA_MATCHFUNC_LIST));
+       numClassDecimal_r5 = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("numClassDecimal_r5", RPA_MATCHFUNC_LIST));
+       numClassDecimal_r6 = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("numClassDecimal_r6", RPA_MATCHFUNC_LIST));
+       classExpr = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("classExpr", RPA_MATCHFUNC_LIST));
+       classExprMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("classExprMatch", RPA_MATCHFUNC_LIST));
+       classMember = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("classMember", RPA_MATCHFUNC_LIST_ALT));
+       classChMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("classChMatch", RPA_MATCHFUNC_LIST));
+       rangeMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("rangeMatch", RPA_MATCHFUNC_LIST));
+       range = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("range", RPA_MATCHFUNC_LIST));
+       classCh = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("classCh", RPA_MATCHFUNC_LIST_ALT));
+       exprCh = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("exprCh", RPA_MATCHFUNC_LIST_ALT));
+       spRegExprCh = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("spRegExprCh", RPA_MATCHFUNC_LIST));
+       escCh = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("escCh", RPA_MATCHFUNC_LIST));
+       spaceOrLf = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("spaceOrLf", RPA_MATCHFUNC_LIST_ALT));
+       comment = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("comment", RPA_MATCHFUNC_LIST));
+       rpaExpr = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("rpaExpr", RPA_MATCHFUNC_LIST_ALT));
+       exprDblQuoteStr = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("exprDblQuoteStr", RPA_MATCHFUNC_LIST));
+       exprDblQuoteStrMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("exprDblQuoteStrMatch", RPA_MATCHFUNC_LIST));
+       exprSnglQuoteStr = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("exprSnglQuoteStr", RPA_MATCHFUNC_LIST));
+       exprSnglQuoteStrMatch = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("exprSnglQuoteStrMatch", RPA_MATCHFUNC_LIST));
+       crlf = (rpa_match_list_t*) MATCH2LIST(rpa_match_list_create("crlf", RPA_MATCHFUNC_LIST));
+
+       rpa_mnode_cat_list(&regExprCh->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&eos->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&regClassCh->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&eos->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&funAbort->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&curlyOpen->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&fnAbort->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&curlyClose->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&funFail->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&curlyOpen->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&fnFail->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&curlyClose->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&funLast->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&curlyOpen->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&fnLast->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&curlyClose->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&funMemberMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_arg1_create(&funFail->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_fun_matchptr, parser, VM_CREATE_FUNFAIL_MATCHPTR)),
+                                          MNODE2LIST(rpa_mnode_callback_arg1_create(&funAbort->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_fun_matchptr, parser, VM_CREATE_FUNABORT_MATCHPTR)),
+                                          MNODE2LIST(rpa_mnode_callback_arg1_create(&funLast->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_fun_matchptr, parser, VM_CREATE_FUNLAST_MATCHPTR)),
+                                          NULL);
+       
+       rpa_mnode_cat_list(&comment->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&pound->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&notlf->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&lf->base, RPA_MATCH_OPTIONAL|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&spaceOrLf->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&space->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&crlf->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&lf->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&escCh->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&backslash->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(anychar, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&classCh->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&escCh->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_esc_val_r5, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&regClassCh->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_val_r5, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&classChMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&classCh->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_val_matchptr, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&range->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&regClassCh->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_val_r5, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&dash->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&regClassCh->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_val_r6, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&rangeMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&range->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_range_matchptr, parser)),
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&classMember->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&rangeMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_mnodeptr, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&classChMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_mnodeptr, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&classExpr->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&squareOpen->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&classMember->base, RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&squareClose->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&classExprMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&classExpr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_class, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&exprCh->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&escCh->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_esc_val_r5, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&regExprCh->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_val_r5, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&exprChMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprCh->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_val_matchptr, parser)),
+                                          NULL);
+                                          
+       rpa_mnode_cat_list(&exprDblQuoteStr->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&notDblQuoteVal->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_cb_push_r5_inc_r4, parser)),
+                                          NULL);
+                                          
+       rpa_mnode_cat_list(&exprDblQuoteStrMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprDblQuoteStr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_strexpr, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&exprSnglQuoteStr->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&notSnglQuoteVal->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_cb_push_r5_inc_r4, parser)),
+                                          NULL);
+                                          
+       rpa_mnode_cat_list(&exprSnglQuoteStrMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprSnglQuoteStr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_strexpr, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&embeddedExprMnodeScb->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&embeddedExprScb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_codeboundary, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&embeddedExprMnodeAcb->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&embeddedExprAcb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_codeboundary, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&embeddedExprMnodeNcb->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&embeddedExprNcb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_codeboundary, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&notExpressionOperand->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&embeddedExprMnodeAcb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_acb_q_mnodeptr_callback, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&embeddedExprMnodeScb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_scb_q_mnodeptr_callback, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&embeddedExprMnodeNcb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_ncb_q_mnodeptr_callback, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&simpMnode->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_mnodeptr, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&notExpression->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&notSign->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_opsign, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&notExpressionOperand->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&notExpressionMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&notExpression->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_seqexpr, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&bracketExpr->head, 
+                                          MNODE2LIST(rpa_mnode_callback_create(&bracketOpen->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprMnode->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&bracketClose->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&bracketExprMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&bracketExpr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_seqexpr, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&embeddedExprNcb->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&oname_ncb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprName->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_nlist, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&cname_ncb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&embeddedExprAcb->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&oname_acb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprName->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_nlist, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&cname_acb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&embeddedExprScb->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&oname_scb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprName->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_nlist, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&cname_scb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&newlineMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&newline->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_newline_matchptr, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&anycharMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&dot->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_anychar_matchptr, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&decNum->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&digit->base, RPA_MATCH_MULTIPLE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&hex->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&digit->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&loHex->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&upHex->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&hexNum->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&hex->base, RPA_MATCH_MULTIPLE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&numClassDecimal_r5->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&pound->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&decNum->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_decnum_r5, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&numClassHex_r5->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&pound->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&zero->base, RPA_MATCH_OPTIONAL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&x->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&hexNum->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_hexnum_r5, parser)),                                       
+                                          NULL);
+
+       rpa_mnode_cat_list(&numClassNumberMatch_r5->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&numClassHex_r5->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&numClassDecimal_r5->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&numClassDecimal_r6->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&pound->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&decNum->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_decnum_r6, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&numClassHex_r6->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&pound->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&zero->base, RPA_MATCH_OPTIONAL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&x->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&hexNum->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_hexnum_r6, parser)),                                       
+                                          NULL);
+
+       rpa_mnode_cat_list(&numClassNumberMatch_r6->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&numClassHex_r6->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&numClassDecimal_r6->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&numClassRange->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&squareOpen->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&numClassNumberMatch_r5->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&dash->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&numClassNumberMatch_r6->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&squareClose->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&numClassSingle->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&squareOpen->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&numClassNumberMatch_r5->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&squareClose->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&numClassMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&numClassSingle->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_val_matchptr, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&numClassRange->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_range_matchptr, parser)),
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&notDblQuote->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&dblQuote->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&notSnglQuote->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&snglQuote->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&notSnglQuoteVal->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&notSnglQuote->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_val_r5, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&notDblQuoteVal->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&notDblQuote->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_val_r5, parser)),
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&notSnglQuoteMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&notSnglQuoteVal->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_val_matchptr, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&notDblQuoteMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&notDblQuoteVal->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_val_matchptr, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&exprStrSnglQuote->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&snglQuote->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&notSnglQuoteMatch->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_cb_mnodeptr, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&snglQuote->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),                                        
+                                          NULL);
+
+       rpa_mnode_cat_list(&exprStrDblQuote->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&dblQuote->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&notDblQuoteMatch->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_cb_mnodeptr, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&dblQuote->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),                                         
+                                          NULL);
+
+       rpa_mnode_cat_list(&exprQStrMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprStrDblQuote->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_seqexpr, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprStrSnglQuote->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_seqexpr, parser)),                                           
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&simpMnode->head, 
+                                          MNODE2LIST(rpa_mnode_callback_create(&notExpressionMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&funMemberMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprQStrMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+//                                        MNODE2LIST(rpa_mnode_callback_create(&embeddedExprNcb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_codeboundary, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&newlineMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&anycharMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&numClassMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&classExprMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&bracketExprMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprChMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&ignore->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&space->base, RPA_MATCH_MULTIPLE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&prettyQuantity->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&space->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&quantity->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_quantity, parser)),
+                                          NULL);       
+
+       rpa_mnode_cat_list(&paddedQMnode->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&ignore->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&simpMnode->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&prettyQuantity->base, RPA_MATCH_OPTIONAL|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&ignore->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&paddedQMnodeNcb->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&ignore->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&embeddedExprNcb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_codeboundary, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&prettyQuantity->base, RPA_MATCH_OPTIONAL|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&ignore->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&paddedQMnodeAcb->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&ignore->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&embeddedExprAcb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_codeboundary, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&prettyQuantity->base, RPA_MATCH_OPTIONAL|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&ignore->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&paddedQMnodeScb->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&ignore->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&embeddedExprScb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_codeboundary, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&prettyQuantity->base, RPA_MATCH_OPTIONAL|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&ignore->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&qMnodeExpr->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&paddedQMnodeAcb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_acb_q_mnodeptr_callback, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&paddedQMnodeScb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_scb_q_mnodeptr_callback, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&paddedQMnodeNcb->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_ncb_q_mnodeptr_callback, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&paddedQMnode->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_q_mnodeptr, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&seqExpr->head,
+                                               MNODE2LIST(rpa_mnode_callback_create(&qMnodeExpr->base, RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                               NULL);
+
+       rpa_mnode_cat_list(&seqExprMatch->head,
+                                               MNODE2LIST(rpa_mnode_callback_create(&seqExpr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_seqexpr, parser)),
+                                               NULL);
+
+       rpa_mnode_cat_list(&seqExprMnode->head,
+                                               MNODE2LIST(rpa_mnode_callback_create(&seqExprMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_mnodeptr, parser)),
+                                               NULL);
+
+       rpa_mnode_cat_list(&opOrSeqExpr->head,
+                                               MNODE2LIST(rpa_mnode_callback_create(&opExpr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_codeboundary, parser)),
+                                           MNODE2LIST(rpa_mnode_callback_create(&seqExpr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_codeboundary, parser)),
+                                               NULL);
+
+       rpa_mnode_cat_list(&opOrSeqExprMatch->head,
+                                               MNODE2LIST(rpa_mnode_callback_create(&opOrSeqExpr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_seqexpr, parser)),
+                                               NULL);
+
+       rpa_mnode_cat_list(&opOrSeqExprMnode->head,
+                                               MNODE2LIST(rpa_mnode_callback_create(&opOrSeqExprMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_mnodeptr_in_altlist, parser)),
+                                               NULL);
+
+
+       rpa_mnode_cat_list(&expr->head,
+                                           MNODE2LIST(rpa_mnode_callback_create(&opOrSeqExpr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                               NULL);
+
+       rpa_mnode_cat_list(&opsign->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&at->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_opsign, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&and->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_opsign, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&contain->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_opsign, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&minus->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_cb_opsign, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&exprMatch->head,
+                                               MNODE2LIST(rpa_mnode_callback_create(&opExprAlt->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_altexpr, parser)),
+                                               MNODE2LIST(rpa_mnode_callback_create(&expr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_seqexpr, parser)),
+                                           NULL);
+
+       rpa_mnode_cat_list(&exprMnode->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_mnodeptr, parser)),
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&exprMnodeInNList->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_mnodeptr_in_nlist, parser)),
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&spOpsign->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&spaceOrLf->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&opsign->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&spaceOrLf->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&spOrSign->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&spaceOrLf->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&or->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&spaceOrLf->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&altExprStartMember->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&opOrSeqExprMnode->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&altExprEndMember->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&spOrSign->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&opOrSeqExprMnode->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&opExprAlt->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&altExprStartMember->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_codeboundary, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&altExprEndMember->base, RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_cb_codeboundary, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&opExpr->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&seqExprMnode->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&spOpsign->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprMnode->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&ignoreLine->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&eos->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&spaceOrLf->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&comment->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&prettyAssign->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&space->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&assign->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_assign, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&space->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&prettyOrr->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&space->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&orr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_assign, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&space->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&prettyBest->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&space->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&best->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_assign, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&space->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&crlf->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&cr->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&lf->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&eoe->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&semicol->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&crlf->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&lf->base, RPA_MATCH_NONE, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&comment->base, RPA_MATCH_OPTIONAL, rpa_parser_mnode_print, parser)),                                      
+                                          MNODE2LIST(rpa_mnode_callback_create(&eos->base, RPA_MATCH_OPTIONAL, rpa_parser_mnode_print, parser)),                                          
+                                          NULL);
+
+       rpa_mnode_cat_list(&alpha->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&lower->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&upper->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&alphanum->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&alpha->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&digit->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&underscore->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&nseparator->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&col->base, RPA_MATCH_OPTIONAL|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&dash->base, RPA_MATCH_OPTIONAL|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&nsalphanum->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&nseparator->base, RPA_MATCH_OPTIONAL|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&alphanum->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&exprName->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&alpha->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&nsalphanum->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&exprNameMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprName->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_nlist, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&namedExprReg->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprNameMatch->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&prettyAssign->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprMnode->base, RPA_MATCH_OPTIONAL|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&space->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&eoe->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&namedExprOrr->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprNameMatch->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&prettyOrr->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprMnodeInNList->base, RPA_MATCH_OPTIONAL|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&space->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&eoe->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&namedExprBest->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprNameMatch->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&prettyBest->base, RPA_MATCH_NONE|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprMnodeInNList->base, RPA_MATCH_OPTIONAL|RPA_REASON_MATCHED, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&space->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&eoe->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+       rpa_mnode_cat_list(&namedExpr->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&namedExprReg->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&namedExprOrr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&namedExprBest->base, RPA_MATCH_OPTIONAL|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+
+
+       rpa_mnode_cat_list(&namedExprMatch->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&space->base, RPA_MATCH_OPTIONAL|RPA_MATCH_MULTIPLE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&namedExpr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_namedexpr, parser)),                                        
+                                          NULL);
+
+       rpa_mnode_cat_list(&rpaExpr->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&ignoreLine->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&namedExprMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          MNODE2LIST(rpa_mnode_callback_create(&exprMatch->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_mnode_print, parser)),
+                                          NULL);
+                                          
+       root = rpa_match_list_create("root", RPA_MATCHFUNC_LIST);
+       rpa_mnode_cat_list(&((rpa_match_list_t *)root)->head,
+                                          MNODE2LIST(rpa_mnode_callback_create(&rpaExpr->base, RPA_MATCH_NONE|RPA_REASON_ALL, rpa_parser_cb_rpaexpr, parser)),
+                                          NULL);
+                                          
+       parser->pVarLinkBnfRoot = pVarLinkRoot = rpa_varlink_create(RPA_VAR_PTR, "root");
+       if (pVarLinkRoot) {
+               pVarLinkRoot->var.userdata4 = MATCH_CLASS_MATCHPTR;
+               pVarLinkRoot->var.v.ptr = (void*) root;
+               pVarLinkRoot->var.finalize = rpa_var_class_destroy;
+               rpa_list_addt(&parser->bnftree, &pVarLinkRoot->lnk);
+       }
+
+       parser->bnfroot = root;
+}
+
+
+static rpa_mnode_t *rpa_varlink_list_add_mnode(rpa_mnode_t *mnode, rpa_head_t *head)
+{
+       rpa_varlink_t *pVarLinkMnodePtr;
+
+       pVarLinkMnodePtr = rpa_varlink_create(RPA_VAR_PTR, "");
+       if (pVarLinkMnodePtr) {
+               pVarLinkMnodePtr->var.userdata4 = MATCH_CLASS_MNODEPTR;
+               pVarLinkMnodePtr->var.v.ptr = (void*) mnode;
+               pVarLinkMnodePtr->var.finalize = rpa_var_class_destroy;
+               rpa_list_addt(head, &pVarLinkMnodePtr->lnk);
+       }
+       return mnode;
+}
+
+
+static rpa_match_t *rpa_varlink_list_add_match(rpa_match_t *match, rpa_head_t *head)
+{
+       rpa_varlink_t *pVarLinkMatch;
+
+       pVarLinkMatch = rpa_varlink_create(RPA_VAR_PTR, "");
+       if (pVarLinkMatch) {
+               pVarLinkMatch->var.userdata4 = MATCH_CLASS_MATCHPTR;
+               pVarLinkMatch->var.v.ptr = (void*) match;
+               pVarLinkMatch->var.finalize = rpa_var_class_destroy;
+               rpa_list_addt(head, &pVarLinkMatch->lnk);
+       }
+       return match;
+}
+
diff --git a/rpa/rpaparser.h b/rpa/rpaparser.h
new file mode 100644 (file)
index 0000000..4bd0c4b
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *  Regular Pattern Analyzer (RPA)
+ *  Copyright (c) 2009-2010 Martin Stoilov
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  Martin Stoilov <martin@rpasearch.com>
+ */
+
+#ifndef _RPAPARSER_H_
+#define _RPAPARSER_H_
+
+#include "rpalist.h"
+#include "rpamatch.h"
+#include "rpawordstack.h"
+#include "rpavm.h"
+#include "rpastat.h"
+#include "rpavarlink.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct rpa_parser_s {
+       rpa_match_t* bnfroot;
+       rpa_varlink_t *pVarLinkBnfRoot;
+       rpa_head_t bnftree;
+       rpa_stat_t stat;
+       rpa_wordstack_t *stack;
+       rpa_asmins_t *vmcode;
+       rpa_word_t vmcode_size;
+       rpa_word_t vmcode_off;
+} rpa_parser_t;
+
+
+rpa_parser_t *rpa_parser_create();
+void rpa_parser_destroy(rpa_parser_t *parser);
+void rpa_parser_setup_bnftree(rpa_parser_t *parser);
+int rpa_parser_exec(rpa_parser_t *parser, const char *input, unsigned long size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rpa/rpaposmnodestack.c b/rpa/rpaposmnodestack.c
new file mode 100644 (file)
index 0000000..fca4764
--- /dev/null