RPA Toolkit
Implemented the PHP extension for RPA.
authorMartin Stoilov <martin@rpasearch.com>
Mon, 20 Jun 2011 06:41:09 +0000 (23:41 -0700)
committerMartin Stoilov <martin@rpasearch.com>
Mon, 20 Jun 2011 06:41:09 +0000 (23:41 -0700)
13 files changed:
phpext/prpa/php_prpa.h
phpext/prpa/prpa.c
phpext/prpa/tests/002.phpt [deleted file]
phpext/prpa/tests/004.phpt [deleted file]
phpext/prpa/tests/006.phpt [deleted file]
phpext/prpa/tests/009.phpt
phpext/prpa/tests/010.phpt
phpext/prpa/tests/011.phpt [new file with mode: 0644]
phpext/prpa/tests/012.phpt [new file with mode: 0644]
rpa/rpadbex.c
rpa/rpaerror.h
rpa/rpastat.c
rpa/rpastatpriv.h

index a3c08bf..f73e642 100644 (file)
@@ -42,6 +42,8 @@ PHP_RINIT_FUNCTION(prpa);
 PHP_RSHUTDOWN_FUNCTION(prpa);
 PHP_MINFO_FUNCTION(prpa);
 PHP_FUNCTION(rpaparse);
+PHP_FUNCTION(rpascan);
+PHP_FUNCTION(rpamatch);
 PHP_FUNCTION(rpa_dbex_version);
 PHP_FUNCTION(rpa_dbex_create);
 PHP_FUNCTION(rpa_dbex_open);
@@ -54,7 +56,6 @@ PHP_FUNCTION(rpa_dbex_last);
 PHP_FUNCTION(rpa_dbex_cfgset);
 PHP_FUNCTION(rpa_dbex_dumpproductions);
 PHP_FUNCTION(rpa_dbex_error);
-
 PHP_FUNCTION(rpa_stat_create);
 PHP_FUNCTION(rpa_stat_scan);
 PHP_FUNCTION(rpa_stat_match);
@@ -62,28 +63,6 @@ PHP_FUNCTION(rpa_stat_parse);
 PHP_FUNCTION(rpa_stat_error);
 
 
-#if 0
-PHP_FUNCTION(rpa_records_create);
-PHP_FUNCTION(rpa_records_length);
-PHP_FUNCTION(rpa_records_get);
-
-PHP_FUNCTION(rpa_dbex_strmatch);
-PHP_FUNCTION(rpa_dbex_set_encoding);
-PHP_FUNCTION(rpa_dbex_match);
-PHP_FUNCTION(rpa_dbex_parse);
-PHP_FUNCTION(rpa_dbex_scan);
-PHP_FUNCTION(rpa_dbex_get_pattern);
-PHP_FUNCTION(rpa_dbex_default_pattern);
-PHP_FUNCTION(rpa_dbex_first_pattern);
-PHP_FUNCTION(rpa_dbex_last_pattern);
-PHP_FUNCTION(rpa_dbex_next_pattern);
-PHP_FUNCTION(rpa_dbex_prev_pattern);
-PHP_FUNCTION(rpa_dbex_pattern_name);
-PHP_FUNCTION(rpa_dbex_pattern_regex);
-PHP_FUNCTION(rpa_dbex_add_callback);
-#endif
-
-
 /* 
        Declare any global variables you may need between the BEGIN
        and END macros here:     
index f53ef14..49f2edf 100644 (file)
@@ -34,8 +34,7 @@
 #include "rparecord.h"
 
 typedef struct _php_rpa_dbex {
-       rpadbex_t* hDbex;
-       zval *zinput;
+       rpadbex_t* dbex;
 #ifdef ZTS
        TSRMLS_D;       
 #endif
@@ -46,7 +45,6 @@ typedef struct _php_rpa_dbex {
 
 typedef struct _php_rpa_stat {
        rpastat_t* stat;
-       zval *zinput;
 #ifdef ZTS
        TSRMLS_D;
 #endif
@@ -54,24 +52,10 @@ typedef struct _php_rpa_stat {
 
 #define PHP_RPA_STAT_RES_NAME "php rpa stat"
 
-
-typedef struct _php_rpa_records {
-       rarray_t* records;
-#ifdef ZTS
-       TSRMLS_D;
-#endif
-} php_rpa_records;
-
-#define PHP_RPA_RECORDS_RES_NAME "php rpa records"
-
-
-static int le_rpa;
 static int le_rpa_dbex;
 static int le_rpa_stat;
-//static int le_rpa_records;
 static void php_rpa_dbex_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
 static void php_rpa_stat_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
-static void php_rpa_records_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
 
 
 /* If you declare any globals in php_prpa.h uncomment this:
@@ -87,6 +71,8 @@ static int le_prpa;
  */
 zend_function_entry prpa_functions[] = {
     PHP_FE(rpaparse, NULL)
+    PHP_FE(rpascan, NULL)
+    PHP_FE(rpamatch, NULL)
     PHP_FE(rpa_dbex_version, NULL)
     PHP_FE(rpa_dbex_create, NULL)
     PHP_FE(rpa_dbex_open, NULL)
@@ -104,28 +90,6 @@ zend_function_entry prpa_functions[] = {
     PHP_FE(rpa_stat_scan, NULL)
     PHP_FE(rpa_stat_parse, NULL)
     PHP_FE(rpa_stat_error, NULL)
-
-
-#if 0
-    PHP_FE(rpa_records_create, NULL)
-    PHP_FE(rpa_records_length, NULL)
-    PHP_FE(rpa_records_get, NULL)
-
-    PHP_FE(rpa_dbex_strmatch, NULL)
-    PHP_FE(rpa_dbex_set_encoding, NULL)
-    PHP_FE(rpa_dbex_match, NULL)
-    PHP_FE(rpa_dbex_parse, NULL)
-    PHP_FE(rpa_dbex_scan, NULL)
-    PHP_FE(rpa_dbex_get_pattern, NULL)
-    PHP_FE(rpa_dbex_default_pattern, NULL)
-    PHP_FE(rpa_dbex_first_pattern, NULL)
-    PHP_FE(rpa_dbex_last_pattern, NULL)
-    PHP_FE(rpa_dbex_next_pattern, NULL)
-    PHP_FE(rpa_dbex_prev_pattern, NULL)
-    PHP_FE(rpa_dbex_pattern_name, NULL)
-    PHP_FE(rpa_dbex_pattern_regex, NULL)
-    PHP_FE(rpa_dbex_add_callback, NULL)
-#endif
        {NULL, NULL, NULL}      /* Must be the last line in prpa_functions[] */
 };
 /* }}} */
@@ -184,8 +148,6 @@ PHP_MINIT_FUNCTION(prpa)
        */
     le_rpa_dbex = zend_register_list_destructors_ex(php_rpa_dbex_dtor, NULL, PHP_RPA_DBEX_RES_NAME, module_number);
     le_rpa_stat = zend_register_list_destructors_ex(php_rpa_stat_dtor, NULL, PHP_RPA_STAT_RES_NAME, module_number);
-//    le_rpa_records = zend_register_list_destructors_ex(php_rpa_records_dtor, NULL, PHP_RPA_RECORDS_RES_NAME, module_number);
-
     REGISTER_LONG_CONSTANT("RPA_ENCODING_BYTE", RPA_ENCODING_BYTE, CONST_CS | CONST_PERSISTENT);
     REGISTER_LONG_CONSTANT("RPA_ENCODING_UTF8", RPA_ENCODING_UTF8, CONST_CS | CONST_PERSISTENT);
     REGISTER_LONG_CONSTANT("RPA_ENCODING_ICASE_UTF8", RPA_ENCODING_ICASE_UTF8, CONST_CS | CONST_PERSISTENT);
@@ -195,7 +157,6 @@ PHP_MINIT_FUNCTION(prpa)
     REGISTER_LONG_CONSTANT("RPA_RECORD_END", RPA_RECORD_END, CONST_CS | CONST_PERSISTENT);
     REGISTER_LONG_CONSTANT("RPA_DBEXCFG_DEBUG", RPA_DBEXCFG_DEBUG, CONST_CS | CONST_PERSISTENT);
     REGISTER_LONG_CONSTANT("RPA_DBEXCFG_OPTIMIZATIONS", RPA_DBEXCFG_OPTIMIZATIONS, CONST_CS | CONST_PERSISTENT);
-
        return SUCCESS;
 }
 /* }}} */
@@ -244,57 +205,6 @@ PHP_MINFO_FUNCTION(prpa)
 /* }}} */
 
 
-PHP_FUNCTION(rpaparse)
-{
-       rpadbex_t *dbex;
-       rpastat_t *stat;
-       long rid;
-       long encoding;
-       long ret, i;
-       char *bnf;
-       int bnf_len;
-       char *input;
-       int input_len;
-       zval *error = NULL;
-       zval *zrecords = NULL;
-       rarray_t *records = rpa_records_create();
-
-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|zz", &bnf, &bnf_len, &encoding, &input, &input_len, &zrecords, &error) == FAILURE) {
-               RETURN_LONG(-1);
-    }
-    dbex = rpa_dbex_create();
-    rpa_dbex_open(dbex);
-    rpa_dbex_load(dbex, bnf, bnf_len);
-    rpa_dbex_close(dbex);
-    rpa_dbex_compile(dbex);
-    stat = rpa_stat_create(dbex, 16000);
-    ret = rpa_stat_parse(stat, rpa_dbex_last(dbex), encoding, input, input, input + input_len, records);
-    if (ret <= 0)
-       goto error;
-    if (zrecords) {
-       rparecord_t *record;
-       array_init(zrecords);
-       for (i = 0; i < rpa_records_length(records); i++) {
-               zval *zrecord;
-               record = rpa_records_slot(records, i);
-               ALLOC_INIT_ZVAL(zrecord);
-               array_init(zrecord);
-               add_assoc_stringl(zrecord, "input", (char*)record->input, record->inputsiz, 1);
-               add_assoc_string(zrecord, "rule", (char*)record->rule, 1);
-               add_assoc_long(zrecord, "type", record->type);
-               add_assoc_long(zrecord, "uid", record->ruleuid);
-               add_next_index_zval(zrecords, zrecord);
-       }
-    }
-
-error:
-       rpa_records_destroy(records);
-       rpa_stat_destroy(stat);
-       rpa_dbex_destroy(dbex);
-       RETURN_LONG(ret);
-}
-
-
 PHP_FUNCTION(rpa_dbex_version)
 {
     RETURN_STRING((char*)rpa_dbex_version(), 1);
@@ -314,68 +224,38 @@ static void php_rpa_stat_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 
 static void php_rpa_dbex_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 {
-    php_rpa_dbex *pPhpDbex = (php_rpa_dbex*)rsrc->ptr;
+    php_rpa_dbex *phpdbex = (php_rpa_dbex*)rsrc->ptr;
 
-    if (pPhpDbex) {
-               rpa_dbex_destroy(pPhpDbex->hDbex);
-/*
-               zval_dtor(pPhpDbex->zcallbacks);
-               Z_DELREF_P(pPhpDbex->zcallbacks);
-               Z_DELREF_P(pPhpDbex->zcallbacks);
-               php_printf("refcnt: %d\n", Z_REFCOUNT_P(pPhpDbex->zcallbacks));
-               efree(pPhpDbex->zcallbacks);
-*/
-               efree(pPhpDbex);
-    }
-}
-
-
-static void php_rpa_records_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
-{
-    php_rpa_records *phprecords = (php_rpa_records*)rsrc->ptr;
-
-    if (phprecords) {
-       rpa_records_destroy(phprecords->records);
-        efree(phprecords);
+    if (phpdbex) {
+               rpa_dbex_destroy(phpdbex->dbex);
+               efree(phpdbex);
     }
 }
 
 
 PHP_FUNCTION(rpa_dbex_create)
 {
-    php_rpa_dbex *pPhpDbex;
+    php_rpa_dbex *phpdbex;
 
-/*
-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &name, &name_len, &age) == FAILURE) {
-               RETURN_FALSE;
-    }
-*/
-
-    pPhpDbex = emalloc(sizeof(php_rpa_dbex));
-    pPhpDbex->hDbex = rpa_dbex_create();
-
-/*
-       ALLOC_INIT_ZVAL(pPhpDbex->zcallbacks);
-       Z_ADDREF_P(pPhpDbex->zcallbacks);
-       array_init(pPhpDbex->zcallbacks);
-*/
-    ZEND_REGISTER_RESOURCE(return_value, pPhpDbex, le_rpa_dbex);
+    phpdbex = emalloc(sizeof(php_rpa_dbex));
+    phpdbex->dbex = rpa_dbex_create();
+    ZEND_REGISTER_RESOURCE(return_value, phpdbex, le_rpa_dbex);
 }
 
 
 PHP_FUNCTION(rpa_dbex_open)
 {
        zval *zres;
-    php_rpa_dbex *pPhpDbex;
+    php_rpa_dbex *phpdbex;
        int ret;
 
     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
                RETURN_LONG(-1);
     }
 
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
+    ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
 
-       ret = rpa_dbex_open(pPhpDbex->hDbex);
+       ret = rpa_dbex_open(phpdbex->dbex);
        RETURN_LONG(ret);
 }
 
@@ -383,15 +263,15 @@ PHP_FUNCTION(rpa_dbex_open)
 PHP_FUNCTION(rpa_dbex_close)
 {
        zval *zres;
-    php_rpa_dbex *pPhpDbex;
+    php_rpa_dbex *phpdbex;
 
     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
                RETURN_LONG(-1);
     }
 
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
+    ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
 
-       rpa_dbex_close(pPhpDbex->hDbex);
+       rpa_dbex_close(phpdbex->dbex);
        RETURN_LONG(0);
 }
 
@@ -399,7 +279,7 @@ PHP_FUNCTION(rpa_dbex_close)
 PHP_FUNCTION(rpa_dbex_load)
 {
        zval *zres;
-    php_rpa_dbex *pPhpDbex;
+    php_rpa_dbex *phpdbex;
        char *patterns;
        int patterns_len;
        int ret;
@@ -409,9 +289,9 @@ PHP_FUNCTION(rpa_dbex_load)
                RETURN_LONG(-1);
     }
 
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
+    ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
 
-    ret = rpa_dbex_load_s(pPhpDbex->hDbex, patterns);
+    ret = rpa_dbex_load_s(phpdbex->dbex, patterns);
        RETURN_LONG(ret);
 }
 
@@ -419,7 +299,7 @@ PHP_FUNCTION(rpa_dbex_load)
 PHP_FUNCTION(rpa_dbex_lookup)
 {
        zval *zres;
-    php_rpa_dbex *pPhpDbex;
+    php_rpa_dbex *phpdbex;
        char *name;
        int name_len;
        long ret;
@@ -428,9 +308,9 @@ PHP_FUNCTION(rpa_dbex_lookup)
                RETURN_LONG(-1);
     }
 
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
+    ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
 
-    ret = rpa_dbex_lookup(pPhpDbex->hDbex, name, name_len);
+    ret = rpa_dbex_lookup(phpdbex->dbex, name, name_len);
        RETURN_LONG(ret);
 }
 
@@ -438,16 +318,16 @@ PHP_FUNCTION(rpa_dbex_lookup)
 PHP_FUNCTION(rpa_dbex_first)
 {
        zval *zres;
-    php_rpa_dbex *pPhpDbex;
+    php_rpa_dbex *phpdbex;
        long ret;
 
     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
                RETURN_LONG(-1);
     }
 
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
+    ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
 
-    ret = rpa_dbex_first(pPhpDbex->hDbex);
+    ret = rpa_dbex_first(phpdbex->dbex);
        RETURN_LONG(ret);
 }
 
@@ -455,16 +335,14 @@ PHP_FUNCTION(rpa_dbex_first)
 PHP_FUNCTION(rpa_dbex_last)
 {
        zval *zres;
-    php_rpa_dbex *pPhpDbex;
+    php_rpa_dbex *phpdbex;
        long ret;
 
     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
                RETURN_LONG(-1);
     }
-
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-
-    ret = rpa_dbex_last(pPhpDbex->hDbex);
+    ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
+    ret = rpa_dbex_last(phpdbex->dbex);
        RETURN_LONG(ret);
 }
 
@@ -472,19 +350,16 @@ PHP_FUNCTION(rpa_dbex_last)
 PHP_FUNCTION(rpa_dbex_compile)
 {
        zval *zres;
-    php_rpa_dbex *pPhpDbex;
+    php_rpa_dbex *phpdbex;
        char *patterns;
        int patterns_len;
        int ret;
 
-
     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
                RETURN_LONG(-1);
     }
-
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-
-    ret = rpa_dbex_compile(pPhpDbex->hDbex);
+    ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
+    ret = rpa_dbex_compile(phpdbex->dbex);
        RETURN_LONG(ret);
 }
 
@@ -492,16 +367,14 @@ PHP_FUNCTION(rpa_dbex_compile)
 PHP_FUNCTION(rpa_dbex_dumpproductions)
 {
        zval *zres;
-    php_rpa_dbex *pPhpDbex;
+    php_rpa_dbex *phpdbex;
        long ret;
 
     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
                RETURN_LONG(-1);
     }
-
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-
-    ret = rpa_dbex_dumpproductions(pPhpDbex->hDbex);
+    ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
+    ret = rpa_dbex_dumpproductions(phpdbex->dbex);
        RETURN_LONG(ret);
 }
 
@@ -509,17 +382,15 @@ PHP_FUNCTION(rpa_dbex_dumpproductions)
 PHP_FUNCTION(rpa_dbex_cfgset)
 {
        zval *zres;
-    php_rpa_dbex *pPhpDbex;
+    php_rpa_dbex *phpdbex;
     long cfg, val;
        long ret;
 
     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &zres, cfg, val) == FAILURE) {
                RETURN_LONG(-1);
     }
-
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-
-    ret = rpa_dbex_cfgset(pPhpDbex->hDbex, cfg, val);
+    ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
+    ret = rpa_dbex_cfgset(phpdbex->dbex, cfg, val);
        RETURN_LONG(ret);
 }
 
@@ -535,6 +406,7 @@ static rchar *dbexmsg[] = {
        "Unresolved expression name.",
        "Invalid parameter.",
        "Failed to compile rule.",
+       "Database is not compiled.",
        "Unknown",
        "Unknown",
        "Unknown",
@@ -560,7 +432,7 @@ static rchar *statmsg[] = {
 };
 
 
-static void rpa_dbex_getdbexerrorstr(rpadbex_t *dbex, char *buffer, size_t size)
+static void rpa_dbex_geterrorstr(rpadbex_t *dbex, char *buffer, size_t size)
 {
        long n = 0;
        char *ptr = buffer;
@@ -568,9 +440,11 @@ static void rpa_dbex_getdbexerrorstr(rpadbex_t *dbex, char *buffer, size_t size)
 
        memset(&errorinfo, 0, sizeof(errorinfo));
     rpa_dbex_lasterrorinfo(dbex, &errorinfo);
-
+    if (!errorinfo.code)
+       return;
     if (errorinfo.mask & RPA_ERRINFO_CODE) {
-        n += snprintf(ptr + n, size - n, "%s Code: %ld. ", dbexmsg[errorinfo.code - 1000], errorinfo.code);
+       if (errorinfo.code >= 1000 && errorinfo.code < 1010)
+               n += snprintf(ptr + n, size - n, "%s Code: %ld. ", dbexmsg[errorinfo.code - 1000], errorinfo.code);
     }
     if (errorinfo.mask & RPA_ERRINFO_LINE) {
         n += snprintf(ptr + n, size - n, "Line: %ld. ", errorinfo.line);
@@ -591,22 +465,20 @@ static void rpa_dbex_getdbexerrorstr(rpadbex_t *dbex, char *buffer, size_t size)
 PHP_FUNCTION(rpa_dbex_error)
 {
        zval *zres;
-       char buffer[2000];
-    php_rpa_dbex *pPhpDbex;
+       char buffer[1000];
+    php_rpa_dbex *phpdbex;
 
        memset(buffer, 0, sizeof(buffer));
     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
                RETURN_LONG(-1);
     }
-
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-    rpa_dbex_getdbexerrorstr(pPhpDbex->hDbex, buffer, sizeof(buffer));
-
+    ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
+    rpa_dbex_geterrorstr(phpdbex->dbex, buffer, sizeof(buffer) - 1);
        RETURN_STRING(buffer, 1);
 }
 
 
-static void rpa_dbex_getstaterrorstr(rpastat_t *stat, char *buffer, size_t size)
+static void rpa_stat_geterrorstr(rpastat_t *stat, char *buffer, size_t size)
 {
        long n = 0;
        char *ptr = buffer;
@@ -614,9 +486,11 @@ static void rpa_dbex_getstaterrorstr(rpastat_t *stat, char *buffer, size_t size)
 
        memset(&errorinfo, 0, sizeof(errorinfo));
     rpa_stat_lasterrorinfo(stat, &errorinfo);
-
+    if (!errorinfo.code)
+       return;
     if (errorinfo.mask & RPA_ERRINFO_CODE) {
-        n += snprintf(ptr + n, size - n, "%s Code: %ld. ", dbexmsg[errorinfo.code - 2000], errorinfo.code);
+       if (errorinfo.code >= 2000 && errorinfo.code < 2010)
+               n += snprintf(ptr + n, size - n, "%s Code: %ld. ", statmsg[errorinfo.code - 2000], errorinfo.code);
     }
     if (errorinfo.mask & RPA_ERRINFO_LINE) {
         n += snprintf(ptr + n, size - n, "Line: %ld. ", errorinfo.line);
@@ -634,20 +508,39 @@ static void rpa_dbex_getstaterrorstr(rpastat_t *stat, char *buffer, size_t size)
 }
 
 
+static void rpa_records2array(const rchar *input, rarray_t *records, zval *zrecords)
+{
+       rlong i;
+
+       rparecord_t *record;
+       array_init(zrecords);
+       for (i = 0; i < rpa_records_length(records); i++) {
+               zval *zrecord;
+               record = rpa_records_slot(records, i);
+               ALLOC_INIT_ZVAL(zrecord);
+               array_init(zrecord);
+               add_assoc_stringl(zrecord, "input", (char*)record->input, record->inputsiz, 1);
+               add_assoc_string(zrecord, "rule", (char*)record->rule, 1);
+               add_assoc_long(zrecord, "type", record->type);
+               add_assoc_long(zrecord, "uid", record->ruleuid);
+               add_assoc_long(zrecord, "offset", record->input - input);
+               add_assoc_long(zrecord, "size", record->inputsiz);
+               add_next_index_zval(zrecords, zrecord);
+       }
+}
+
 PHP_FUNCTION(rpa_stat_error)
 {
        zval *zres;
-       char buffer[2000];
+       char buffer[1000];
     php_rpa_stat *phpstat;
 
        memset(buffer, 0, sizeof(buffer));
     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
                RETURN_LONG(-1);
     }
-
     ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zres, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
-    rpa_stat_geterrorstr(phpstat->stat, buffer, sizeof(buffer));
-
+    rpa_stat_geterrorstr(phpstat->stat, buffer, sizeof(buffer) - 1);
        RETURN_STRING(buffer, 1);
 }
 
@@ -655,19 +548,17 @@ PHP_FUNCTION(rpa_stat_error)
 PHP_FUNCTION(rpa_stat_create)
 {
        zval *zres;
-    php_rpa_dbex *pPhpDbex;
+    php_rpa_dbex *phpdbex;
     php_rpa_stat *phpstat;
        int ret;
        long stackSize = 0L;
 
-
     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zres, &stackSize) == FAILURE) {
                RETURN_LONG(-1);
     }
-
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
+    ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
     phpstat = emalloc(sizeof(php_rpa_stat));
-    phpstat->stat = rpa_stat_create(pPhpDbex->hDbex, stackSize);
+    phpstat->stat = rpa_stat_create(phpdbex->dbex, stackSize);
     ZEND_REGISTER_RESOURCE(return_value, phpstat, le_rpa_stat);
 }
 
@@ -708,12 +599,11 @@ PHP_FUNCTION(rpa_stat_scan)
     }
     ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zstat, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
     ret = rpa_stat_scan(phpstat->stat, rid, encoding, input, input, input + input_len, &where);
-       if (ret) {
+       if (ret > 0) {
                ZVAL_LONG(zwhere, where - input);
        } else {
                ZVAL_NULL(zwhere);
        }
-
        RETURN_LONG(ret);
 }
 
@@ -738,19 +628,7 @@ PHP_FUNCTION(rpa_stat_parse)
     if (ret <= 0)
        goto error;
     if (zrecords) {
-       rparecord_t *record;
-       array_init(zrecords);
-       for (i = 0; i < rpa_records_length(records); i++) {
-               zval *zrecord;
-               record = rpa_records_slot(records, i);
-               ALLOC_INIT_ZVAL(zrecord);
-               array_init(zrecord);
-               add_assoc_stringl(zrecord, "input", (char*)record->input, record->inputsiz, 1);
-               add_assoc_string(zrecord, "rule", (char*)record->rule, 1);
-               add_assoc_long(zrecord, "type", record->type);
-               add_assoc_long(zrecord, "uid", record->ruleuid);
-               add_next_index_zval(zrecords, zrecord);
-       }
+       rpa_records2array(input, records, zrecords);
     }
 
 error:
@@ -759,503 +637,193 @@ error:
 }
 
 
-PHP_FUNCTION(rpa_records_create)
-{
-    php_rpa_records *phprecords;
-
-    phprecords = emalloc(sizeof(php_rpa_records));
-    phprecords->records = rpa_records_create();
-
-    ZEND_REGISTER_RESOURCE(return_value, phprecords, le_rpa_dbex);
-}
-
-
-#if 0
-static php_cbinfo *php_cbinfo_create(php_rpa_dbex *pPhpDbex, const char *php_callback, zval *userdata)
-{
-       php_cbinfo *pCbInfo;
-
-       if ((pCbInfo = emalloc(sizeof(php_cbinfo))) == NULL)
-               return NULL;
-
-       pCbInfo->pPhpDbex = pPhpDbex;
-       pCbInfo->php_callback = estrdup(php_callback);
-       pCbInfo->userdata = userdata;
-       if (userdata) {
-               ZVAL_ADDREF(userdata);
-//             Z_SET_ISREF_P(userdata);
-       }
-       return pCbInfo;
-}
-
-
-static void php_cbinfo_destroy(php_cbinfo *pCbInfo)
+PHP_FUNCTION(rpaparse)
 {
-       if (!pCbInfo)
-               return;
-       if (pCbInfo->php_callback)
-               efree(pCbInfo->php_callback);
-       if (pCbInfo->userdata) {
-               if (ZVAL_REFCOUNT(pCbInfo->userdata) == 1) {
-                       zval_ptr_dtor(&pCbInfo->userdata);
-               } else {
-                       ZVAL_DELREF(pCbInfo->userdata);
-               }
-       }
-       efree(pCbInfo);
-}
-
+       char buffer[1000];
+       rpadbex_t *dbex = NULL;
+       rpastat_t *stat = NULL;
+       long rid;
+       long encoding;
+       long ret, i;
+       char *bnf;
+       int bnf_len;
+       char *input;
+       int input_len;
+       zval *zerror = NULL;
+       zval *zrecords = NULL;
+       rarray_t *records = rpa_records_create();
 
-static void php_do_rpa_dbex_strmatch(INTERNAL_FUNCTION_PARAMETERS, int global) /* {{{ */
-{
-    /* parameters */
-    char             *subject;          /* String to match against */
-    char             *regex;            /* Regular expression */
-    int               subject_len;
-    int               regex_len;
-       int                               ret = 0;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &subject, 
-                                                         &subject_len,
-                                                         &regex,
-                                                         &regex_len) == FAILURE) {
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|zz", &bnf, &bnf_len, &encoding, &input, &input_len, &zrecords, &zerror) == FAILURE) {
                RETURN_LONG(-1);
     }
-/*
-       ret = emalloc(subject_len + regex_len + 100);
-       php_sprintf(ret, "Hello from rpalib, subject: %s, regex: %s", subject, regex);
-    RETURN_STRING(ret, 0);
-*/
-       ret = rpa_dbex_strmatch(subject, regex);
-       RETURN_LONG(ret);
-}
-
-
-/* {{{ proto int rpa_dbex_strmatch(string subject, string pattern)
-   Perform a regular expression match */
-PHP_FUNCTION(rpa_dbex_strmatch)
-{
-    php_do_rpa_dbex_strmatch(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
-}
-
-
-PHP_FUNCTION(rpa_dbex_greetme)
-{
-    zval *zname;
-
-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) {
-        RETURN_NULL();
-    }
-
-    convert_to_string(zname);
-
-    php_printf("Hello ");
-    PHPWRITE(Z_STRVAL_P(zname), Z_STRLEN_P(zname));
-    php_printf(" ");
-
-    RETURN_TRUE;
-}
-
-
-
-
-
-
-PHP_FUNCTION(rpa_dbex_load_string)
-{
-       zval *zres;
-    php_rpa_dbex *pPhpDbex;
-       char *patterns;
-       int patterns_len;
-       int ret;
-
-
-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &patterns, &patterns_len) == FAILURE) {
-               RETURN_LONG(-1);
+    memset(buffer, 0, sizeof(buffer));
+    dbex = rpa_dbex_create();
+    if (rpa_dbex_open(dbex) < 0)
+       goto dbexerror;
+    if (rpa_dbex_load(dbex, bnf, bnf_len) < 0)
+       goto dbexerror;
+    rpa_dbex_close(dbex);
+    if (rpa_dbex_compile(dbex) < 0)
+       goto dbexerror;
+    stat = rpa_stat_create(dbex, 16000);
+    ret = rpa_stat_parse(stat, rpa_dbex_last(dbex), encoding, input, input, input + input_len, records);
+    if (ret < 0)
+       goto staterror;
+    if (ret > 0 && zrecords) {
+               rpa_records2array(input, records, zrecords);
     }
 
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-
-    ret = rpa_dbex_load_string(pPhpDbex->hDbex, patterns);
+       if (zerror) {
+               ZVAL_NULL(zerror);
+       }
+       rpa_records_destroy(records);
+       rpa_stat_destroy(stat);
+       rpa_dbex_destroy(dbex);
        RETURN_LONG(ret);
-}
 
+dbexerror:
+       if (zerror) {
+               rpa_dbex_geterrorstr(dbex, buffer, sizeof(buffer) - 1);
+               ZVAL_STRING(zerror, buffer, 1);
+       }
+       rpa_records_destroy(records);
+       rpa_stat_destroy(stat);
+       rpa_dbex_destroy(dbex);
+       RETURN_LONG(-1);
 
-PHP_FUNCTION(rpa_dbex_set_encoding)
-{
-       zval *zres;
-    php_rpa_dbex *pPhpDbex;
-       char *patterns;
-       long encoding;
-       int patterns_len;
-       int ret;
-
-
-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &encoding) == FAILURE) {
-               RETURN_LONG(-1);
-    }
-
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-
-    ret = rpa_dbex_set_encoding(pPhpDbex->hDbex, encoding);
-       RETURN_LONG(ret);
+staterror:
+       if (zerror) {
+               rpa_stat_geterrorstr(stat, buffer, sizeof(buffer) - 1);
+               ZVAL_STRING(zerror, buffer, 1);
+       }
+       rpa_records_destroy(records);
+       rpa_stat_destroy(stat);
+       rpa_dbex_destroy(dbex);
+       RETURN_LONG(-1);
 }
 
 
-PHP_FUNCTION(rpa_dbex_match)
+PHP_FUNCTION(rpascan)
 {
-       zval *zdbex;
-       zval *zpattern;
-       zval *zinput;
-    php_rpa_dbex *pPhpDbex;
-    php_rpa_pattern *pPhpPattern;
+       char buffer[1000];
+       rpadbex_t *dbex = NULL;
+       rpastat_t *stat = NULL;
+       long rid;
+       long encoding;
+       long ret, i;
+       char *bnf;
+       int bnf_len;
        char *input;
+       const rchar *where = NULL;
        int input_len;
-       int ret;
+       zval *zerror = NULL;
+       zval *zwhere = NULL;
 
-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz", &zdbex, &zpattern, &zinput) == FAILURE) {
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|zz", &bnf, &bnf_len, &encoding, &input, &input_len, &zwhere, &zerror) == FAILURE) {
                RETURN_LONG(-1);
     }
-       input = Z_STRVAL_P(zinput);
-       input_len = Z_STRLEN_P(zinput);
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zdbex, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-    ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zpattern, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
-#ifdef ZTS
-       pPhpDbex->tsrm_ls = TSRMLS_C;
-#endif
-       pPhpDbex->zinput = zinput;
-    ret = rpa_dbex_match(pPhpDbex->hDbex, pPhpPattern->hPattern, input, input, input + input_len);
+    memset(buffer, 0, sizeof(buffer));
+    dbex = rpa_dbex_create();
+    if (rpa_dbex_open(dbex) < 0)
+       goto dbexerror;
+    if (rpa_dbex_load(dbex, bnf, bnf_len) < 0)
+       goto dbexerror;
+    rpa_dbex_close(dbex);
+    if (rpa_dbex_compile(dbex) < 0)
+       goto dbexerror;
+    stat = rpa_stat_create(dbex, 16000);
+    ret = rpa_stat_scan(stat, rpa_dbex_last(dbex), encoding, input, input, input + input_len, &where);
+    if (ret < 0)
+       goto staterror;
+    if (zwhere) {
+               if (ret > 0 && where) {
+                       ZVAL_LONG(zwhere, where - input);
+               } else {
+                       ZVAL_NULL(zwhere);
+               }
+    }
+       if (zerror) {
+               ZVAL_NULL(zerror);
+       }
+       rpa_stat_destroy(stat);
+       rpa_dbex_destroy(dbex);
        RETURN_LONG(ret);
-}
 
+dbexerror:
+       if (zerror) {
+               rpa_dbex_geterrorstr(dbex, buffer, sizeof(buffer) - 1);
+               ZVAL_STRING(zerror, buffer, 1);
+       }
+       rpa_stat_destroy(stat);
+       rpa_dbex_destroy(dbex);
+       RETURN_LONG(-1);
 
-PHP_FUNCTION(rpa_dbex_parse)
-{
-       zval *zdbex;
-       zval *zpattern;
-       zval *zinput;
-    php_rpa_dbex *pPhpDbex;
-    php_rpa_pattern *pPhpPattern;
-       char *input;
-       int input_len;
-       int ret;
+staterror:
+       if (zerror) {
+               rpa_stat_geterrorstr(stat, buffer, sizeof(buffer) - 1);
+               ZVAL_STRING(zerror, buffer, 1);
+       }
+       rpa_stat_destroy(stat);
+       rpa_dbex_destroy(dbex);
+       RETURN_LONG(-1);
 
-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz", &zdbex, &zpattern, &zinput) == FAILURE) {
-               RETURN_LONG(-1);
-    }
-       input = Z_STRVAL_P(zinput);
-       input_len = Z_STRLEN_P(zinput);
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zdbex, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-    ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zpattern, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
-#ifdef ZTS
-       pPhpDbex->tsrm_ls = TSRMLS_C;
-#endif
-       pPhpDbex->zinput = zinput;
-    ret = rpa_dbex_parse(pPhpDbex->hDbex, pPhpPattern->hPattern, input, input, input + input_len);
-       RETURN_LONG(ret);
 }
 
 
-PHP_FUNCTION(rpa_dbex_scan)
+PHP_FUNCTION(rpamatch)
 {
-       zval *zdbex;
-       zval *zpattern;
-       zval *zinput;
-       zval *zwhere;
-    php_rpa_dbex *pPhpDbex;
-    php_rpa_pattern *pPhpPattern;
+       char buffer[1000];
+       rpadbex_t *dbex = NULL;
+       rpastat_t *stat = NULL;
+       long rid;
+       long encoding;
+       long ret, i;
+       char *bnf;
+       int bnf_len;
        char *input;
-       const char *where = NULL;
        int input_len;
-       int ret;
+       zval *zerror = NULL;
 
-    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrzz", &zdbex, &zpattern, &zinput, &zwhere) == FAILURE) {
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|z", &bnf, &bnf_len, &encoding, &input, &input_len, &zerror) == FAILURE) {
                RETURN_LONG(-1);
     }
-       input = Z_STRVAL_P(zinput);
-       input_len = Z_STRLEN_P(zinput);
-    ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zdbex, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-    ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zpattern, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
-#ifdef ZTS
-       pPhpDbex->tsrm_ls = TSRMLS_C;
-#endif
-       pPhpDbex->zinput = zinput;
-    ret = rpa_dbex_scan(pPhpDbex->hDbex, pPhpPattern->hPattern, input, input, input + input_len, &where);
-       if (ret) {
-               ZVAL_LONG(zwhere, where - input);
-       } else {
-               ZVAL_NULL(zwhere);
+    memset(buffer, 0, sizeof(buffer));
+    dbex = rpa_dbex_create();
+    if (rpa_dbex_open(dbex) < 0)
+       goto dbexerror;
+    if (rpa_dbex_load(dbex, bnf, bnf_len) < 0)
+       goto dbexerror;
+    rpa_dbex_close(dbex);
+    if (rpa_dbex_compile(dbex) < 0)
+       goto dbexerror;
+    stat = rpa_stat_create(dbex, 16000);
+    ret = rpa_stat_match(stat, rpa_dbex_last(dbex), encoding, input, input, input + input_len);
+    if (ret < 0)
+       goto staterror;
+       if (zerror) {
+               ZVAL_NULL(zerror);
        }
-
+       rpa_stat_destroy(stat);
+       rpa_dbex_destroy(dbex);
        RETURN_LONG(ret);
-}
-
-
-PHP_FUNCTION(rpa_dbex_get_pattern)
-{
-       zval *zres;
-       php_rpa_dbex *pPhpDbex;
-       php_rpa_pattern *pPhpPattern;
-       char *name;
-       int name_len;
-       rpa_pattern_handle hPattern;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &name, &name_len) == FAILURE) {
-               RETURN_FALSE;
-       }
-       ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-       hPattern = rpa_dbex_get_pattern(pPhpDbex->hDbex, name);
-       if (!hPattern)
-               RETURN_FALSE;
-       pPhpPattern = emalloc(sizeof(php_rpa_pattern));
-       pPhpPattern->hPattern = hPattern;
-       ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
-}
-
-
-PHP_FUNCTION(rpa_dbex_default_pattern)
-{
-       zval *zres;
-       php_rpa_dbex *pPhpDbex;
-       php_rpa_pattern *pPhpPattern;
-       rpa_pattern_handle hPattern;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
-               RETURN_FALSE;
-       }
-       ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-       hPattern = rpa_dbex_default_pattern(pPhpDbex->hDbex);
-       if (!hPattern)
-               RETURN_FALSE;
-       pPhpPattern = emalloc(sizeof(php_rpa_pattern));
-       pPhpPattern->hPattern = hPattern;
-       ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
-}
-
-
-PHP_FUNCTION(rpa_dbex_first_pattern)
-{
-       zval *zres;
-       php_rpa_dbex *pPhpDbex;
-       php_rpa_pattern *pPhpPattern;
-       rpa_pattern_handle hPattern;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
-               RETURN_FALSE;
-       }
-       ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-       hPattern = rpa_dbex_first_pattern(pPhpDbex->hDbex);
-       if (!hPattern)
-               RETURN_FALSE;
-       pPhpPattern = emalloc(sizeof(php_rpa_pattern));
-       pPhpPattern->hPattern = hPattern;
-       ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
-}
-
-
-PHP_FUNCTION(rpa_dbex_last_pattern)
-{
-       zval *zres;
-       php_rpa_dbex *pPhpDbex;
-       php_rpa_pattern *pPhpPattern;
-       rpa_pattern_handle hPattern;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
-               RETURN_FALSE;
-       }
-       ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-       hPattern = rpa_dbex_last_pattern(pPhpDbex->hDbex);
-       if (!hPattern)
-               RETURN_FALSE;
-       pPhpPattern = emalloc(sizeof(php_rpa_pattern));
-       pPhpPattern->hPattern = hPattern;
-       ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
-}
-
-
-PHP_FUNCTION(rpa_dbex_next_pattern)
-{
-       zval *zresFirst, *zresSecond;
-       php_rpa_dbex *pPhpDbex;
-       php_rpa_pattern *pPhpPatternCur;
-       php_rpa_pattern *pPhpPattern;
-       rpa_pattern_handle hPattern;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &zresFirst, &zresSecond) == FAILURE) {
-               RETURN_FALSE;
-       }
-       ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresFirst, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-    ZEND_FETCH_RESOURCE(pPhpPatternCur, php_rpa_pattern*, &zresSecond, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
-               
-       hPattern = rpa_dbex_next_pattern(pPhpDbex ? pPhpDbex->hDbex : NULL, pPhpPatternCur ? pPhpPatternCur->hPattern : NULL);
-       if (!hPattern)
-               RETURN_FALSE;
-       pPhpPattern = emalloc(sizeof(php_rpa_pattern));
-       pPhpPattern->hPattern = hPattern;
-       ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
-}
-
-
-PHP_FUNCTION(rpa_dbex_prev_pattern)
-{
-       zval *zresFirst, *zresSecond;
-       php_rpa_dbex *pPhpDbex;
-       php_rpa_pattern *pPhpPatternCur;
-       php_rpa_pattern *pPhpPattern;
-       rpa_pattern_handle hPattern;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &zresFirst, &zresSecond) == FAILURE) {
-               RETURN_FALSE;
-       }
-       ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresFirst, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-    ZEND_FETCH_RESOURCE(pPhpPatternCur, php_rpa_pattern*, &zresSecond, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
-               
-       hPattern = rpa_dbex_prev_pattern(pPhpDbex ? pPhpDbex->hDbex : NULL, pPhpPatternCur ? pPhpPatternCur->hPattern : NULL);
-       if (!hPattern)
-               RETURN_FALSE;
-       pPhpPattern = emalloc(sizeof(php_rpa_pattern));
-       pPhpPattern->hPattern = hPattern;
-       ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
-}
 
-
-PHP_FUNCTION(rpa_dbex_pattern_name)
-{
-       zval *zresFirst, *zresSecond;
-       php_rpa_dbex *pPhpDbex;
-       php_rpa_pattern *pPhpPattern;
-       const char *name;
-       char *ret;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &zresFirst, &zresSecond) == FAILURE) {
-               RETURN_FALSE;
-       }
-       ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresFirst, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-    ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zresSecond, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
-               
-       name = rpa_dbex_pattern_name(pPhpDbex ? pPhpDbex->hDbex : NULL, pPhpPattern ? pPhpPattern->hPattern : NULL);
-       if (!name)
-               RETURN_FALSE;
-       ret = estrdup(name);
-       RETURN_STRING(ret, 0);
-}
-
-
-PHP_FUNCTION(rpa_dbex_pattern_regex)
-{
-       zval *zresFirst, *zresSecond;
-       php_rpa_dbex *pPhpDbex;
-       php_rpa_pattern *pPhpPattern;
-       long int seq = 0;
-       const char *regex;
-       char *ret;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|l", &zresFirst, &zresSecond, &seq) == FAILURE) {
-               RETURN_FALSE;
-       }
-       ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresFirst, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
-    ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zresSecond, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
-               
-       regex = rpa_dbex_pattern_regex(pPhpDbex ? pPhpDbex->hDbex : NULL, pPhpPattern ? pPhpPattern->hPattern : NULL, seq);
-       if (!regex)
-               RETURN_FALSE;
-       ret = estrdup(regex);
-       RETURN_STRING(ret, 0);
-}
-
-
-static int php_rpa_callback_proxy(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
-{
-       php_cbinfo *pCbInfo = (php_cbinfo*)userdata;
-       zval *retval_ptr = NULL;  /* Function return value */
-    zval **args[7];           /* Argument to pass to function */
-       zval *zcallback;
-       zval *zname;
-       zval *zoffset;
-       zval *zsize;
-       zval *zreason;
-       zval *zuserdata;
-       zval *zempty;
-       int ret = size;
-#ifdef ZTS
-       TSRMLS_D = pCbInfo->pPhpDbex->tsrm_ls;
-#endif
-
-       MAKE_STD_ZVAL(zcallback);
-       MAKE_STD_ZVAL(zname);
-       MAKE_STD_ZVAL(zoffset);
-       MAKE_STD_ZVAL(zsize);
-       MAKE_STD_ZVAL(zreason);
-       MAKE_STD_ZVAL(zuserdata);
-       MAKE_STD_ZVAL(zempty);
-
-       ZVAL_STRING(zcallback, pCbInfo->php_callback, 1);
-       ZVAL_LONG(zsize, size);
-       ZVAL_LONG(zreason, reason);
-       ZVAL_LONG(zempty, 0);
-       ZVAL_LONG(zoffset, input - start);
-       ZVAL_STRING(zname, name, 1);
-
-       args[0] = &zname;
-       if (pCbInfo->userdata) {
-               args[1] = &pCbInfo->userdata;
-       } else {
-               args[1] = &zempty;
-       }
-
-
-       args[2] = &zoffset;
-       args[3] = &zsize;
-       args[4] = &zreason;
-       args[5] = &pCbInfo->pPhpDbex->zinput;
-
-
-       if (call_user_function_ex(EG(function_table), NULL, zcallback, &retval_ptr, 6, args, 0, NULL TSRMLS_CC) == SUCCESS && retval_ptr) {
-               convert_to_long(retval_ptr);
-               ret = (int) Z_LVAL_P(retval_ptr);
-               zval_ptr_dtor(&retval_ptr);
-       } else {
-               if (!EG(exception)) {
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call function: %s()", Z_STRVAL_P(zcallback));
-               }
+dbexerror:
+       if (zerror) {
+               rpa_dbex_geterrorstr(dbex, buffer, sizeof(buffer) - 1);
+               ZVAL_STRING(zerror, buffer, 1);
        }
+       rpa_stat_destroy(stat);
+       rpa_dbex_destroy(dbex);
+       RETURN_LONG(-1);
 
-/*
-       zval_ptr_dtor(&zcallback);
-       zval_ptr_dtor(&zname);
-       zval_ptr_dtor(&zsize);
-       zval_ptr_dtor(&zreason);
-       zval_ptr_dtor(&zuserdata);
-       zval_ptr_dtor(&zoffset);
-       zval_ptr_dtor(&zempty);
-*/
-
-       return ret;
-}
-
-
-PHP_FUNCTION(rpa_dbex_add_callback)
-{
-       zval *zresDbex, *zresCallback, *zresUserData = NULL;
-       php_rpa_dbex *pPhpDbex;
-       php_rpa_pattern *pPhpPattern;
-       char *name;
-       long reason;
-       int name_len = 0;
-       char *callback;
-       int callback_len = 0;
-       unsigned long ret = 0;
-       php_cbinfo *pCbInfo;
-
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsls|z", &zresDbex, &name, &name_len, &reason, 
-                                                         &callback, &callback_len, &zresUserData) == FAILURE) {
-               RETURN_LONG(-1);
+staterror:
+       if (zerror) {
+               rpa_stat_geterrorstr(stat, buffer, sizeof(buffer) - 1);
+               ZVAL_STRING(zerror, buffer, 1);
        }
-       ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresDbex, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
+       rpa_stat_destroy(stat);
+       rpa_dbex_destroy(dbex);
+       RETURN_LONG(-1);
 
-       pCbInfo = php_cbinfo_create(pPhpDbex, callback, zresUserData);
-       ret = rpa_dbex_add_callback(pPhpDbex ? pPhpDbex->hDbex : NULL, name, reason, php_rpa_callback_proxy, pCbInfo);
-       RETURN_LONG(ret);
 }
 
-#endif
diff --git a/phpext/prpa/tests/002.phpt b/phpext/prpa/tests/002.phpt
deleted file mode 100644 (file)
index 40442c9..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
---TEST--
-rpa_dbex_strmatch("martin stoilov", "[a-z]+")
---SKIPIF--
-<?php if (!extension_loaded("prpa")) print "skip"; ?>
---FILE--
-<?php 
-echo (rpa_dbex_strmatch("martin stoilov", "[a-z]+"));
-echo "\n"
-
-?>
---EXPECT--
-6
diff --git a/phpext/prpa/tests/004.phpt b/phpext/prpa/tests/004.phpt
deleted file mode 100644 (file)
index 01427af..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
---TEST--
-rpa_dbex_add_callback
---SKIPIF--
-<?php if (!extension_loaded("prpa")) echo "skip\n"; ?>
---FILE--
-<?php 
-      function matched_callback($name, $userdata, $offset, $size, $reason, $input)
-      {
-        $works = "callback: " . $name . ", " . $reason . ", " . $size . ", " . $input . "\n";
-       echo($works);
-       return $size;
-      }
-
-      $hDbex = rpa_dbex_create();
-      rpa_dbex_add_callback($hDbex, "nam.", RPA_REASON_MATCHED, 'matched_callback');
-//      rpa_dbex_add_callback($hDbex, "alpha", RPA_REASON_MATCHED, 'matched_callback', "hop hop");
-      rpa_dbex_open($hDbex);
-      rpa_dbex_load_string($hDbex, "alpha ::= [a-z]");
-      rpa_dbex_load_string($hDbex, "name ::= <:alpha:>+");
-      rpa_dbex_load_string($hDbex, "number ::= [0-9]+");
-      rpa_dbex_load_string($hDbex, "myname ::= <:name:>");
-      rpa_dbex_close($hDbex);
-      $pattern = rpa_dbex_get_pattern($hDbex, "myname");
-      $myname = "martin stoilov";
-      $ret = rpa_dbex_match($hDbex, $pattern, $myname);
-      $matched = "matched: " . substr($myname, 0, $ret) . "\n";
-      echo($matched);
-      for ($p = rpa_dbex_first_pattern($hDbex); $p; $p = rpa_dbex_next_pattern($hDbex, $p)) {
-         echo(rpa_dbex_pattern_name($hDbex, $p));
-         echo(" ::= ");
-         echo(rpa_dbex_pattern_regex($hDbex, $p));
-         echo("\n");
-      }
-
-      unset($hDbex);
-?>
---EXPECT--
-callback: name, 1024, 6, martin stoilov
-matched: martin
-alpha ::= [a-z]
-name ::= <:alpha:>+
-number ::= [0-9]+
-myname ::= <:name:>
diff --git a/phpext/prpa/tests/006.phpt b/phpext/prpa/tests/006.phpt
deleted file mode 100644 (file)
index 7d3754e..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
---TEST--
-rpa_dbex_add_callback
---SKIPIF--
-<?php if (!extension_loaded("prpa")) echo "skip\n"; ?>
---FILE--
-<?php 
-      function matched_callback($name, $userdata, $offset, $size, $reason, $input)
-      {
-        $works = "callback: " . $name . ", " . $reason . ", " . $size . ", " . $input . "\n";
-       echo($works);
-       return $size;
-      }
-
-      $hDbex = rpa_dbex_create();
-      rpa_dbex_add_callback($hDbex, "nam.", RPA_REASON_MATCHED, 'matched_callback');
-      rpa_dbex_open($hDbex);
-      rpa_dbex_load_string($hDbex, "alpha ::= [a-z]");
-      rpa_dbex_load_string($hDbex, "name ::= <:alpha:>+");
-      rpa_dbex_load_string($hDbex, "number ::= [0-9]+");
-      rpa_dbex_load_string($hDbex, "myname ::= <:name:>");
-      rpa_dbex_close($hDbex);
-      $pattern = rpa_dbex_get_pattern($hDbex, "myname");
-      $myname = "martin stoilov";
-      $ret = rpa_dbex_parse($hDbex, $pattern, $myname);
-      $matched = "matched: " . substr($myname, 0, $ret) . "\n";
-      echo($matched);
-      for ($p = rpa_dbex_first_pattern($hDbex); $p; $p = rpa_dbex_next_pattern($hDbex, $p)) {
-         echo(rpa_dbex_pattern_name($hDbex, $p));
-         echo(" ::= ");
-         echo(rpa_dbex_pattern_regex($hDbex, $p));
-         echo("\n");
-      }
-
-      unset($hDbex);
-?>
---EXPECT--
-callback: name, 1024, 6, martin stoilov
-matched: martin
-alpha ::= [a-z]
-name ::= <:alpha:>+
-number ::= [0-9]+
-myname ::= <:name:>
index d221b71..2e12eda 100644 (file)
@@ -27,10 +27,13 @@ rpa_dbex_parse($hDbex, $pattern, $myname)
        if ($pattern == -1) {
                die(rpa_dbex_error($hDbex). "\n");
        }
-       $myname = "Kosko Stoilov";
+       $myname = "John Smith";
        $stat = rpa_stat_create($hDbex, 0);
        
        $ret = rpa_stat_parse($stat, $pattern, RPA_ENCODING_ICASE_UTF8, $myname, $records);
+       if ($ret < 0) {
+               die(rpa_stat_error($stat). "\n");       
+       }
        $matched = "matched: " . substr($myname, 0, $ret) . "\n";
        echo($matched);
        
@@ -41,11 +44,17 @@ rpa_dbex_parse($hDbex, $pattern, $myname)
                        echo("END   ");
                else
                        echo("UNKNOWN");
-               echo ($record['uid'] . ", " . $record['rule'] . ": " . $record['input'] . "\n");
+               echo ("(" . $record['offset'] . ", " . $record['size'] . ") " . $record['uid'] . ", " . $record['rule'] . ": " . $record['input'] . "\n");
        }
        unset($stat);
        unset($hDbex);
       
 ?>
 --EXPECT--
-matched: Martin Stoilov
+matched: John Smith
+START (0, 10) 3, name: John Smith
+START (0, 4) 1, first: John
+END   (0, 4) 1, first: John
+START (5, 5) 2, last: Smith
+END   (5, 5) 2, last: Smith
+END   (0, 10) 3, name: John Smith
index e02c520..626936e 100644 (file)
@@ -12,8 +12,10 @@ rpaparse($bnf, $input, $records, $error);
        "first ::= [a-z]+\n" .
        "last ::= [a-z]+\n" .
        "name ::= <first> ' '+ <last>\n";
-       $myname = "Kosko Stoilov";      
-       $ret = rpaparse($bnf, RPA_ENCODING_ICASE_UTF8, $myname, $records);
+       $myname = "John Smith"; 
+       $ret = rpaparse($bnf, RPA_ENCODING_ICASE_UTF8, $myname, $records, $error);
+       if ($ret < 0)
+               die($error . "\n");
        $matched = "matched: " . substr($myname, 0, $ret) . "\n";
        echo($matched);
        
@@ -26,7 +28,12 @@ rpaparse($bnf, $input, $records, $error);
                        echo("UNKNOWN");
                echo ($record['uid'] . ", " . $record['rule'] . ": " . $record['input'] . "\n");
        }
-      
 ?>
 --EXPECT--
-matched: Martin Stoilov
+matched: John Smith
+START 3, name: John Smith
+START 1, first: John
+END   1, first: John
+START 2, last: Smith
+END   2, last: Smith
+END   3, name: John Smith
diff --git a/phpext/prpa/tests/011.phpt b/phpext/prpa/tests/011.phpt
new file mode 100644 (file)
index 0000000..5ebfba0
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+rpascan($bnf, $input, $where, $error);
+--SKIPIF--
+<?php if (!extension_loaded("prpa")) echo "skip\n"; ?>
+--FILE--
+<?php 
+       $where = 0;
+       $error = 0;
+       $bnf = "#!emitid first 1\n" .
+       "#!emitid last 2\n" .
+       "#!emitid name 3\n" .
+       "first ::= [a-z]+\n" .
+       "last ::= [a-z]+\n" .
+       "name ::= <first> ' '+ <last>\n";
+       $myname = "     : John Smith";  
+       if (($ret = rpascan($bnf, RPA_ENCODING_ICASE_UTF8, $myname, $where, $error)) < 0)
+               die($error . "\n");
+       echo("matched: " . substr($myname, $where, $ret) . " @ " . $where . "\n");
+?>
+--EXPECT--
+matched: John Smith @ 7
diff --git a/phpext/prpa/tests/012.phpt b/phpext/prpa/tests/012.phpt
new file mode 100644 (file)
index 0000000..7e515e0
--- /dev/null
@@ -0,0 +1,20 @@
+--TEST--
+rpamatch($bnf, $input, $error);
+--SKIPIF--
+<?php if (!extension_loaded("prpa")) echo "skip\n"; ?>
+--FILE--
+<?php 
+       $error = 0;
+       $bnf = "#!emitid first 1\n" .
+       "#!emitid last 2\n" .
+       "#!emitid name 3\n" .
+       "first ::= [a-z]+\n" .
+       "last ::= [a-z]+\n" .
+       "name ::= <first> ' '+ <last>\n";
+       $myname = "John Smith"; 
+       if (($ret = rpascan($bnf, RPA_ENCODING_ICASE_UTF8, $myname, $error)) < 0)
+               die($error . "\n");
+       echo("matched: " . substr($myname, 0, $ret) . "\n");
+?>
+--EXPECT--
+matched: John Smith
index 0bc76d3..148c4fc 100644 (file)
@@ -50,6 +50,7 @@ struct rpadbex_s {
        rulong headoff;
        rulong optimizations:1;
        rulong debug:1;
+       rulong compiled:1;
 };
 
 static rparecord_t *rpa_dbex_rulerecord(rpadbex_t *dbex, rparule_t rid);
@@ -1685,6 +1686,7 @@ rinteger rpa_dbex_open(rpadbex_t *dbex)
                r_object_destroy((robject_t *)dbex->rules);
                dbex->rules = NULL;
        }
+       dbex->compiled = 0;
        return 0;
 }
 
@@ -2161,7 +2163,6 @@ static rinteger rpa_dbex_compile_rule(rpadbex_t *dbex, rparule_t rid)
                return -1;
        info->codeoff = codeoff;
        info->codesiz = rvm_codegen_getcodesize(dbex->co->cg) - codeoff;
-
        return 0;
 }
 
@@ -2197,7 +2198,7 @@ rinteger rpa_dbex_compile(rpadbex_t *dbex)
                RPA_DBEX_SETERRINFO_NAME(dbex, labelerr->name->str, labelerr->name->size);
                return -1;
        }
-
+       dbex->compiled = 1;
        return 0;
 }
 
@@ -2210,6 +2211,10 @@ rvm_asmins_t *rpa_dbex_executable(rpadbex_t *dbex)
                RPA_DBEX_SETERRINFO_CODE(dbex, RPA_E_NOTCLOSED);
                return NULL;
        }
+       if (!dbex->compiled || rvm_codegen_getcodesize(dbex->co->cg) == 0) {
+               RPA_DBEX_SETERRINFO_CODE(dbex, RPA_E_NOTCOMPILED);
+               return NULL;
+       }
        return rvm_codegen_getcode(dbex->co->cg, 0);
 }
 
@@ -2224,6 +2229,10 @@ rlong rpa_dbex_executableoffset(rpadbex_t *dbex, rparule_t rid)
                RPA_DBEX_SETERRINFO_CODE(dbex, RPA_E_NOTCLOSED);
                return -1;
        }
+       if (!dbex->compiled) {
+               RPA_DBEX_SETERRINFO_CODE(dbex, RPA_E_NOTCOMPILED);
+               return -1;
+       }
        info = (rpa_ruleinfo_t *)r_harray_get(dbex->rules, rid);
        if (!info) {
                RPA_DBEX_SETERRINFO_CODE(dbex, RPA_E_NOTFOUND);
index 76da961..5f00cf3 100644 (file)
 #define RPA_E_UNRESOLVED_SYMBOL 1007
 #define RPA_E_PARAM 1008
 #define RPA_E_COMPILE 1009
+#define RPA_E_NOTCOMPILED 1010
 
-#define RPA_E_EXECUTION 2000
-#define RPA_E_USERABORT 2001
-#define RPA_E_RULEABORT 2002
+#define RPA_E_EXECUTION 2001
+#define RPA_E_USERABORT 2002
+#define RPA_E_RULEABORT 2003
 
 /**
  * \typedef rpaerror_t
index 03d9a73..c0bb1e0 100644 (file)
@@ -131,8 +131,21 @@ static rlong rpa_stat_exec_rid(rpastat_t *stat, rparule_t rid, ruinteger encodin
 {
        rlong topsiz = 0;
        rpainput_t *ptp;
+       rlong offset;
+       rvm_asmins_t *exec;
 
-       if ((topsiz = rpa_stat_exec(stat, rpa_dbex_executable(stat->dbex), rpa_dbex_executableoffset(stat->dbex, rid), encoding, input, start, end, records)) < 0) {
+
+       exec = rpa_dbex_executable(stat->dbex);
+       if (!exec) {
+               RPA_STAT_SETERROR_CODE(stat, RPA_E_EXECUTION);
+               return -1;
+       }
+       offset = rpa_dbex_executableoffset(stat->dbex, rid);
+       if (offset < 0) {
+               RPA_STAT_SETERROR_CODE(stat, RPA_E_EXECUTION);
+               return -1;
+       }
+       if ((topsiz = rpa_stat_exec(stat, exec, offset, encoding, input, start, end, records)) < 0) {
                return -1;
        }
        if (topsiz <= 0)
index 51a958f..282c1c5 100644 (file)
@@ -14,7 +14,7 @@
 extern "C" {
 #endif
 
-#define RPA_STAT_SETERROR_CODE(__d__, __e__) do { (__d__)->err.code = __e__; } while (0)
+#define RPA_STAT_SETERROR_CODE(__d__, __e__) do { (__d__)->err.code = __e__; (__d__)->err.mask |= RPA_ERRINFO_CODE;} while (0)
 #define RPA_STAT_SETERRINFO_OFFSET(__d__, __o__) do { (__d__)->err.offset = __o__; (__d__)->err.mask |= RPA_ERRINFO_OFFSET; } while (0)
 #define RPA_STAT_SETERRINFO_RULEUID(__d__, __r__) do { (__d__)->err.ruleid = __r__; (__d__)->err.mask |= RPA_ERRINFO_RULEID; } while (0)
 #define RPA_STAT_SETERRINFO_NAME(__d__, __n__, __s__) do { \