RPA Toolkit
modified the returned error.
[rpatk.git] / phpext / prpa / prpa.c
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2008 The PHP Group                                |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Author:                                                              |
16   +----------------------------------------------------------------------+
17 */
18
19 /* $Id: header,v 1.16.2.1.2.1.2.1 2008/02/07 19:39:50 iliaa Exp $ */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "php_prpa.h"
29 #include "TSRM/TSRM.h"
30 #include "rpadbex.h"
31 #include "rpastat.h"
32 #include "rpastatpriv.h"
33 #include "rpaerror.h"
34 #include "rparecord.h"
35
36 typedef struct _php_rpa_dbex {
37         rpadbex_t* dbex;
38 #ifdef ZTS
39         TSRMLS_D;       
40 #endif
41 } php_rpa_dbex;
42
43 #define PHP_RPA_DBEX_RES_NAME "php rpa dbex"
44
45
46 typedef struct _php_rpa_stat {
47         rpastat_t* stat;
48 #ifdef ZTS
49         TSRMLS_D;
50 #endif
51 } php_rpa_stat;
52
53 #define PHP_RPA_STAT_RES_NAME "php rpa stat"
54
55 static int le_rpa_dbex;
56 static int le_rpa_stat;
57 static void php_rpa_dbex_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
58 static void php_rpa_stat_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
59
60
61 /* If you declare any globals in php_prpa.h uncomment this:
62 ZEND_DECLARE_MODULE_GLOBALS(prpa)
63 */
64
65 /* True global resources - no need for thread safety here */
66 static int le_prpa;
67
68 /* {{{ prpa_functions[]
69  *
70  * Every user visible function must have an entry in prpa_functions[].
71  */
72 zend_function_entry prpa_functions[] = {
73     PHP_FE(rpaparse, NULL)
74     PHP_FE(rpascan, NULL)
75     PHP_FE(rpamatch, NULL)
76     PHP_FE(rpa_dbex_version, NULL)
77     PHP_FE(rpa_dbex_create, NULL)
78     PHP_FE(rpa_dbex_open, NULL)
79     PHP_FE(rpa_dbex_close, NULL)
80     PHP_FE(rpa_dbex_load, NULL)
81     PHP_FE(rpa_dbex_compile, NULL)
82     PHP_FE(rpa_dbex_lookup, NULL)
83     PHP_FE(rpa_dbex_first, NULL)
84     PHP_FE(rpa_dbex_last, NULL)
85     PHP_FE(rpa_dbex_cfgset, NULL)
86     PHP_FE(rpa_dbex_dumpproductions, NULL)
87     PHP_FE(rpa_dbex_error, NULL)
88     PHP_FE(rpa_stat_create, NULL)
89     PHP_FE(rpa_stat_match, NULL)
90     PHP_FE(rpa_stat_scan, NULL)
91     PHP_FE(rpa_stat_parse, NULL)
92     PHP_FE(rpa_stat_error, NULL)
93         {NULL, NULL, NULL}      /* Must be the last line in prpa_functions[] */
94 };
95 /* }}} */
96
97 /* {{{ prpa_module_entry
98  */
99 zend_module_entry prpa_module_entry = {
100 #if ZEND_MODULE_API_NO >= 20010901
101         STANDARD_MODULE_HEADER,
102 #endif
103         "prpa",
104         prpa_functions,
105         PHP_MINIT(prpa),
106         PHP_MSHUTDOWN(prpa),
107         PHP_RINIT(prpa),                /* Replace with NULL if there's nothing to do at request start */
108         PHP_RSHUTDOWN(prpa),    /* Replace with NULL if there's nothing to do at request end */
109         PHP_MINFO(prpa),
110 #if ZEND_MODULE_API_NO >= 20010901
111         "0.1", /* Replace with version number for your extension */
112 #endif
113         STANDARD_MODULE_PROPERTIES
114 };
115 /* }}} */
116
117 #ifdef COMPILE_DL_PRPA
118 ZEND_GET_MODULE(prpa)
119 #endif
120
121 /* {{{ PHP_INI
122  */
123 /* Remove comments and fill if you need to have entries in php.ini
124 PHP_INI_BEGIN()
125     STD_PHP_INI_ENTRY("prpa.global_value",      "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_prpa_globals, prpa_globals)
126     STD_PHP_INI_ENTRY("prpa.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_prpa_globals, prpa_globals)
127 PHP_INI_END()
128 */
129 /* }}} */
130
131 /* {{{ php_prpa_init_globals
132  */
133 /* Uncomment this function if you have INI entries
134 static void php_prpa_init_globals(zend_prpa_globals *prpa_globals)
135 {
136         prpa_globals->global_value = 0;
137         prpa_globals->global_string = NULL;
138 }
139 */
140 /* }}} */
141
142 /* {{{ PHP_MINIT_FUNCTION
143  */
144 PHP_MINIT_FUNCTION(prpa)
145 {
146         /* If you have INI entries, uncomment these lines 
147         REGISTER_INI_ENTRIES();
148         */
149     le_rpa_dbex = zend_register_list_destructors_ex(php_rpa_dbex_dtor, NULL, PHP_RPA_DBEX_RES_NAME, module_number);
150     le_rpa_stat = zend_register_list_destructors_ex(php_rpa_stat_dtor, NULL, PHP_RPA_STAT_RES_NAME, module_number);
151     REGISTER_LONG_CONSTANT("RPA_ENCODING_BYTE", RPA_ENCODING_BYTE, CONST_CS | CONST_PERSISTENT);
152     REGISTER_LONG_CONSTANT("RPA_ENCODING_UTF8", RPA_ENCODING_UTF8, CONST_CS | CONST_PERSISTENT);
153     REGISTER_LONG_CONSTANT("RPA_ENCODING_ICASE_UTF8", RPA_ENCODING_ICASE_UTF8, CONST_CS | CONST_PERSISTENT);
154     REGISTER_LONG_CONSTANT("RPA_ENCODING_UTF16LE", RPA_ENCODING_UTF16LE, CONST_CS | CONST_PERSISTENT);
155     REGISTER_LONG_CONSTANT("RPA_ENCODING_ICASE_UTF16LE", RPA_ENCODING_ICASE_UTF16LE, CONST_CS | CONST_PERSISTENT);
156     REGISTER_LONG_CONSTANT("RPA_RECORD_START", RPA_RECORD_START, CONST_CS | CONST_PERSISTENT);
157     REGISTER_LONG_CONSTANT("RPA_RECORD_END", RPA_RECORD_END, CONST_CS | CONST_PERSISTENT);
158     REGISTER_LONG_CONSTANT("RPA_DBEXCFG_DEBUG", RPA_DBEXCFG_DEBUG, CONST_CS | CONST_PERSISTENT);
159     REGISTER_LONG_CONSTANT("RPA_DBEXCFG_OPTIMIZATIONS", RPA_DBEXCFG_OPTIMIZATIONS, CONST_CS | CONST_PERSISTENT);
160         return SUCCESS;
161 }
162 /* }}} */
163
164 /* {{{ PHP_MSHUTDOWN_FUNCTION
165  */
166 PHP_MSHUTDOWN_FUNCTION(prpa)
167 {
168         /* uncomment this line if you have INI entries
169         UNREGISTER_INI_ENTRIES();
170         */
171         return SUCCESS;
172 }
173 /* }}} */
174
175 /* Remove if there's nothing to do at request start */
176 /* {{{ PHP_RINIT_FUNCTION
177  */
178 PHP_RINIT_FUNCTION(prpa)
179 {
180         return SUCCESS;
181 }
182 /* }}} */
183
184 /* Remove if there's nothing to do at request end */
185 /* {{{ PHP_RSHUTDOWN_FUNCTION
186  */
187 PHP_RSHUTDOWN_FUNCTION(prpa)
188 {
189         return SUCCESS;
190 }
191 /* }}} */
192
193 /* {{{ PHP_MINFO_FUNCTION
194  */
195 PHP_MINFO_FUNCTION(prpa)
196 {
197         php_info_print_table_start();
198         php_info_print_table_header(2, "prpa support", "enabled");
199         php_info_print_table_end();
200
201         /* Remove comments if you have entries in php.ini
202         DISPLAY_INI_ENTRIES();
203         */
204 }
205 /* }}} */
206
207
208 PHP_FUNCTION(rpa_dbex_version)
209 {
210     RETURN_STRING((char*)rpa_dbex_version(), 1);
211 }
212
213
214 static void php_rpa_stat_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
215 {
216     php_rpa_stat *phpstat = (php_rpa_stat*)rsrc->ptr;
217
218     if (phpstat) {
219         rpa_stat_destroy(phpstat->stat);
220         efree(phpstat);
221     }
222 }
223
224
225 static void php_rpa_dbex_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
226 {
227     php_rpa_dbex *phpdbex = (php_rpa_dbex*)rsrc->ptr;
228
229     if (phpdbex) {
230                 rpa_dbex_destroy(phpdbex->dbex);
231                 efree(phpdbex);
232     }
233 }
234
235
236 PHP_FUNCTION(rpa_dbex_create)
237 {
238     php_rpa_dbex *phpdbex;
239
240     phpdbex = emalloc(sizeof(php_rpa_dbex));
241     phpdbex->dbex = rpa_dbex_create();
242     ZEND_REGISTER_RESOURCE(return_value, phpdbex, le_rpa_dbex);
243 }
244
245
246 PHP_FUNCTION(rpa_dbex_open)
247 {
248         zval *zres;
249     php_rpa_dbex *phpdbex;
250         int ret;
251
252     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
253                 RETURN_LONG(-1);
254     }
255
256     ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
257
258         ret = rpa_dbex_open(phpdbex->dbex);
259         RETURN_LONG(ret);
260 }
261
262
263 PHP_FUNCTION(rpa_dbex_close)
264 {
265         zval *zres;
266     php_rpa_dbex *phpdbex;
267
268     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
269                 RETURN_LONG(-1);
270     }
271
272     ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
273
274         rpa_dbex_close(phpdbex->dbex);
275         RETURN_LONG(0);
276 }
277
278
279 PHP_FUNCTION(rpa_dbex_load)
280 {
281         zval *zres;
282     php_rpa_dbex *phpdbex;
283         char *patterns;
284         int patterns_len;
285         int ret;
286
287
288     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &patterns, &patterns_len) == FAILURE) {
289                 RETURN_LONG(-1);
290     }
291
292     ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
293
294     ret = rpa_dbex_load_s(phpdbex->dbex, patterns);
295         RETURN_LONG(ret);
296 }
297
298
299 PHP_FUNCTION(rpa_dbex_lookup)
300 {
301         zval *zres;
302     php_rpa_dbex *phpdbex;
303         char *name;
304         int name_len;
305         long ret;
306
307     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &name, &name_len) == FAILURE) {
308                 RETURN_LONG(-1);
309     }
310
311     ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
312
313     ret = rpa_dbex_lookup(phpdbex->dbex, name, name_len);
314         RETURN_LONG(ret);
315 }
316
317
318 PHP_FUNCTION(rpa_dbex_first)
319 {
320         zval *zres;
321     php_rpa_dbex *phpdbex;
322         long ret;
323
324     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
325                 RETURN_LONG(-1);
326     }
327
328     ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
329
330     ret = rpa_dbex_first(phpdbex->dbex);
331         RETURN_LONG(ret);
332 }
333
334
335 PHP_FUNCTION(rpa_dbex_last)
336 {
337         zval *zres;
338     php_rpa_dbex *phpdbex;
339         long ret;
340
341     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
342                 RETURN_LONG(-1);
343     }
344     ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
345     ret = rpa_dbex_last(phpdbex->dbex);
346         RETURN_LONG(ret);
347 }
348
349
350 PHP_FUNCTION(rpa_dbex_compile)
351 {
352         zval *zres;
353     php_rpa_dbex *phpdbex;
354         char *patterns;
355         int patterns_len;
356         int ret;
357
358     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
359                 RETURN_LONG(-1);
360     }
361     ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
362     ret = rpa_dbex_compile(phpdbex->dbex);
363         RETURN_LONG(ret);
364 }
365
366
367 PHP_FUNCTION(rpa_dbex_dumpproductions)
368 {
369         zval *zres;
370     php_rpa_dbex *phpdbex;
371         long ret;
372
373     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
374                 RETURN_LONG(-1);
375     }
376     ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
377     ret = rpa_dbex_dumpproductions(phpdbex->dbex);
378         RETURN_LONG(ret);
379 }
380
381
382 PHP_FUNCTION(rpa_dbex_cfgset)
383 {
384         zval *zres;
385     php_rpa_dbex *phpdbex;
386     long cfg, val;
387         long ret;
388
389     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &zres, cfg, val) == FAILURE) {
390                 RETURN_LONG(-1);
391     }
392     ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
393     ret = rpa_dbex_cfgset(phpdbex->dbex, cfg, val);
394         RETURN_LONG(ret);
395 }
396
397
398 static rchar *dbexmsg[] = {
399         "OK",
400         "Out of memory",
401         "Invalid input.",
402         "Expression database is not open.",
403         "Expression database is not closed.",
404         "Expression name is not found.",
405         "Syntax error.",
406         "Unresolved expression name.",
407         "Invalid parameter.",
408         "Failed to compile rule.",
409         "Database is not compiled.",
410         "Unknown",
411         "Unknown",
412         "Unknown",
413         "Unknown",
414         "Unknown",
415         "Unknown",
416         "Unknown",
417 };
418
419
420 static rchar *statmsg[] = {
421         "OK",
422         "Execution error.",
423         "Execution aborted by user.",
424         "Aborted on expression.",
425         "Unknown",
426         "Unknown",
427         "Unknown",
428         "Unknown",
429         "Unknown",
430         "Unknown",
431         "Unknown",
432 };
433
434
435 static zval *rpa_zvalerror(rpa_errinfo_t *errorinfo)
436 {
437         long n = 0;
438         char buffer[1000];
439         char *ptr = buffer;
440         size_t size = sizeof(buffer) - 1;
441         zval *zerror = NULL;
442
443         memset(buffer, 0, sizeof(buffer));
444         ALLOC_INIT_ZVAL(zerror);
445         array_init(zerror);
446     if (errorinfo->mask & RPA_ERRINFO_CODE) {
447         if (errorinfo->code >= 1000 && errorinfo->code < 1010)
448                 n += snprintf(ptr + n, size - n, "%s Code: %ld. ", dbexmsg[errorinfo->code - 1000], errorinfo->code);
449         else if (errorinfo->code >= 2000 && errorinfo->code < 2010)
450                 n += snprintf(ptr + n, size - n, "%s Code: %ld. ", statmsg[errorinfo->code - 2000], errorinfo->code);
451         else
452                 n += snprintf(ptr + n, size - n, "Error Code: %ld. ", errorinfo->code);
453         add_assoc_long(zerror, "code", errorinfo->code);
454     }
455     if (errorinfo->mask & RPA_ERRINFO_LINE) {
456         n += snprintf(ptr + n, size - n, "Line: %ld. ", errorinfo->line);
457         add_assoc_long(zerror, "line", errorinfo->line);
458     }
459     if (errorinfo->mask & RPA_ERRINFO_OFFSET) {
460         n += snprintf(ptr + n, size - n, "Offset: %ld. ", errorinfo->offset);
461         add_assoc_long(zerror, "offset", errorinfo->offset);
462     }
463     if (errorinfo->mask & RPA_ERRINFO_RULEID) {
464         n += snprintf(ptr + n, size - n, "RuleId: %ld. ", errorinfo->ruleid);
465         add_assoc_long(zerror, "rid", errorinfo->ruleid);
466     }
467     if (errorinfo->mask & RPA_ERRINFO_NAME) {
468         n += snprintf(ptr + n, size - n, "Name: %s. ", errorinfo->name);
469         add_assoc_string(zerror, "name", errorinfo->name, 1);
470     }
471         add_assoc_stringl(zerror, "message", buffer, n, 1);
472     return zerror;
473 }
474
475
476 PHP_FUNCTION(rpa_dbex_error)
477 {
478         zval *zres;
479     php_rpa_dbex *phpdbex;
480     zval *zerror = NULL;
481     rpa_errinfo_t errorinfo;
482
483         memset(&errorinfo, 0, sizeof(errorinfo));
484     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
485                 RETURN_LONG(-1);
486     }
487     ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
488     rpa_dbex_lasterrorinfo(phpdbex->dbex, &errorinfo);
489     zerror = rpa_zvalerror(&errorinfo);
490         RETURN_ZVAL(zerror, 1, 0);
491 }
492
493
494 PHP_FUNCTION(rpa_stat_error)
495 {
496         zval *zres;
497         char buffer[1000];
498     php_rpa_stat *phpstat;
499     zval *zerror = NULL;
500     rpa_errinfo_t errorinfo;
501
502         memset(&errorinfo, 0, sizeof(errorinfo));
503     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
504                 RETURN_LONG(-1);
505     }
506     ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zres, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
507     rpa_stat_lasterrorinfo(phpstat->stat, &errorinfo);
508     zerror = rpa_zvalerror(&errorinfo);
509         RETURN_ZVAL(zerror, 1, 0);
510 }
511
512
513 static void rpa_records2array(const rchar *input, rarray_t *records, zval *zrecords)
514 {
515         rlong i;
516
517         rparecord_t *record;
518         array_init(zrecords);
519         for (i = 0; i < rpa_records_length(records); i++) {
520                 zval *zrecord;
521                 record = rpa_records_slot(records, i);
522                 ALLOC_INIT_ZVAL(zrecord);
523                 array_init(zrecord);
524                 add_assoc_stringl(zrecord, "input", (char*)record->input, record->inputsiz, 1);
525                 add_assoc_string(zrecord, "rule", (char*)record->rule, 1);
526                 add_assoc_long(zrecord, "type", record->type);
527                 add_assoc_long(zrecord, "uid", record->ruleuid);
528                 add_assoc_long(zrecord, "offset", record->input - input);
529                 add_assoc_long(zrecord, "size", record->inputsiz);
530                 add_next_index_zval(zrecords, zrecord);
531         }
532 }
533
534
535 PHP_FUNCTION(rpa_stat_create)
536 {
537         zval *zres;
538     php_rpa_dbex *phpdbex;
539     php_rpa_stat *phpstat;
540         int ret;
541         long stackSize = 0L;
542
543     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zres, &stackSize) == FAILURE) {
544                 RETURN_LONG(-1);
545     }
546     ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
547     phpstat = emalloc(sizeof(php_rpa_stat));
548     phpstat->stat = rpa_stat_create(phpdbex->dbex, stackSize);
549     ZEND_REGISTER_RESOURCE(return_value, phpstat, le_rpa_stat);
550 }
551
552
553 PHP_FUNCTION(rpa_stat_match)
554 {
555         zval *zstat;
556     php_rpa_stat *phpstat;
557         long rid;
558         long encoding;
559         long ret;
560         char *input;
561         int input_len;
562
563     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlls", &zstat, &rid, &encoding, &input, &input_len) == FAILURE) {
564                 RETURN_LONG(-1);
565     }
566     ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zstat, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
567     ret = rpa_stat_match(phpstat->stat, rid, encoding, input, input, input + input_len);
568         RETURN_LONG(ret);
569 }
570
571
572 PHP_FUNCTION(rpa_stat_scan)
573 {
574         zval *zstat;
575     php_rpa_stat *phpstat;
576         long rid;
577         long encoding;
578         long ret;
579         char *input;
580         int input_len;
581         zval *zwhere;
582         const char *where = NULL;
583
584     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllsz", &zstat, &rid, &encoding, &input, &input_len, &zwhere) == FAILURE) {
585                 RETURN_LONG(-1);
586     }
587     ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zstat, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
588     ret = rpa_stat_scan(phpstat->stat, rid, encoding, input, input, input + input_len, &where);
589         if (ret > 0) {
590                 ZVAL_LONG(zwhere, where - input);
591         } else {
592                 ZVAL_NULL(zwhere);
593         }
594         RETURN_LONG(ret);
595 }
596
597
598 PHP_FUNCTION(rpa_stat_parse)
599 {
600         zval *zstat;
601     php_rpa_stat *phpstat;
602         long rid;
603         long encoding;
604         long ret, i;
605         char *input;
606         int input_len;
607         zval *zrecords = NULL;
608         rarray_t *records = rpa_records_create();
609
610     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlls|z", &zstat, &rid, &encoding, &input, &input_len, &zrecords) == FAILURE) {
611                 RETURN_LONG(-1);
612     }
613     ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zstat, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
614     ret = rpa_stat_parse(phpstat->stat, rid, encoding, input, input, input + input_len, records);
615     if (ret <= 0) {
616         if (zrecords)
617                 ZVAL_NULL(zrecords);
618         rpa_records_destroy(records);
619         RETURN_LONG(ret);
620     }
621     if (zrecords) {
622         rpa_records2array(input, records, zrecords);
623     }
624         rpa_records_destroy(records);
625         RETURN_LONG(ret);
626 }
627
628
629 PHP_FUNCTION(rpaparse)
630 {
631         rpadbex_t *dbex = NULL;
632         rpastat_t *stat = NULL;
633         long rid;
634         long encoding;
635         long ret, i;
636         char *bnf;
637         int bnf_len;
638         char *input;
639         int input_len;
640         zval *zerror = NULL;
641         zval *zrecords = NULL;
642         rarray_t *records = rpa_records_create();
643
644     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|zz", &bnf, &bnf_len, &encoding, &input, &input_len, &zrecords, &zerror) == FAILURE) {
645                 RETURN_LONG(-1);
646     }
647     dbex = rpa_dbex_create();
648     if (rpa_dbex_open(dbex) < 0)
649         goto dbexerror;
650     if (rpa_dbex_load(dbex, bnf, bnf_len) < 0)
651         goto dbexerror;
652     rpa_dbex_close(dbex);
653     if (rpa_dbex_compile(dbex) < 0)
654         goto dbexerror;
655     stat = rpa_stat_create(dbex, 16000);
656     ret = rpa_stat_parse(stat, rpa_dbex_last(dbex), encoding, input, input, input + input_len, records);
657     if (ret < 0)
658         goto staterror;
659     if (ret > 0 && zrecords) {
660         rpa_records2array(input, records, zrecords);
661     }
662
663         if (zerror) {
664                 ZVAL_NULL(zerror);
665         }
666         rpa_records_destroy(records);
667         rpa_stat_destroy(stat);
668         rpa_dbex_destroy(dbex);
669         RETURN_LONG(ret);
670
671 dbexerror:
672         if (zerror) {
673                 rpa_errinfo_t errorinfo;
674                 memset(&errorinfo, 0, sizeof(errorinfo));
675                 rpa_dbex_lasterrorinfo(dbex, &errorinfo);
676                 zval *temp = rpa_zvalerror(&errorinfo);
677                 ZVAL_ZVAL(zerror, temp, 0, 1);
678         }
679 //      if (zrecords)
680 //              ZVAL_NULL(zrecords);
681         rpa_records_destroy(records);
682         rpa_stat_destroy(stat);
683         rpa_dbex_destroy(dbex);
684         RETURN_LONG(-1);
685
686 staterror:
687         if (zerror) {
688                 rpa_errinfo_t errorinfo;
689                 memset(&errorinfo, 0, sizeof(errorinfo));
690                 rpa_stat_lasterrorinfo(stat, &errorinfo);
691                 zval *temp = rpa_zvalerror(&errorinfo);
692                 ZVAL_ZVAL(zerror, temp, 0, 1);
693         }
694 //      if (zrecords)
695 //              ZVAL_NULL(zrecords);
696         rpa_records_destroy(records);
697         rpa_stat_destroy(stat);
698         rpa_dbex_destroy(dbex);
699         RETURN_LONG(-1);
700 }
701
702
703 PHP_FUNCTION(rpascan)
704 {
705         rpadbex_t *dbex = NULL;
706         rpastat_t *stat = NULL;
707         long rid;
708         long encoding;
709         long ret, i;
710         char *bnf;
711         int bnf_len;
712         char *input;
713         const rchar *where = NULL;
714         int input_len;
715         zval *zerror = NULL;
716         zval *zwhere = NULL;
717
718     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|zz", &bnf, &bnf_len, &encoding, &input, &input_len, &zwhere, &zerror) == FAILURE) {
719                 RETURN_LONG(-1);
720     }
721     dbex = rpa_dbex_create();
722     if (rpa_dbex_open(dbex) < 0)
723         goto dbexerror;
724     if (rpa_dbex_load(dbex, bnf, bnf_len) < 0)
725         goto dbexerror;
726     rpa_dbex_close(dbex);
727     if (rpa_dbex_compile(dbex) < 0)
728         goto dbexerror;
729     stat = rpa_stat_create(dbex, 16000);
730     ret = rpa_stat_scan(stat, rpa_dbex_last(dbex), encoding, input, input, input + input_len, &where);
731     if (ret < 0)
732         goto staterror;
733     if (zwhere) {
734                 if (ret > 0 && where) {
735                         ZVAL_LONG(zwhere, where - input);
736                 } else {
737                         ZVAL_NULL(zwhere);
738                 }
739     }
740         if (zerror) {
741                 ZVAL_NULL(zerror);
742         }
743         rpa_stat_destroy(stat);
744         rpa_dbex_destroy(dbex);
745         RETURN_LONG(ret);
746
747 dbexerror:
748         if (zerror) {
749                 rpa_errinfo_t errorinfo;
750                 memset(&errorinfo, 0, sizeof(errorinfo));
751                 rpa_dbex_lasterrorinfo(dbex, &errorinfo);
752                 zval *temp = rpa_zvalerror(&errorinfo);
753                 ZVAL_ZVAL(zerror, temp, 0, 1);
754         }
755         rpa_stat_destroy(stat);
756         rpa_dbex_destroy(dbex);
757         RETURN_LONG(-1);
758
759 staterror:
760         if (zerror) {
761                 rpa_errinfo_t errorinfo;
762                 memset(&errorinfo, 0, sizeof(errorinfo));
763                 rpa_stat_lasterrorinfo(stat, &errorinfo);
764                 zval *temp = rpa_zvalerror(&errorinfo);
765                 ZVAL_ZVAL(zerror, temp, 0, 1);
766         }
767         rpa_stat_destroy(stat);
768         rpa_dbex_destroy(dbex);
769         RETURN_LONG(-1);
770 }
771
772
773 PHP_FUNCTION(rpamatch)
774 {
775         rpadbex_t *dbex = NULL;
776         rpastat_t *stat = NULL;
777         long rid;
778         long encoding;
779         long ret, i;
780         char *bnf;
781         int bnf_len;
782         char *input;
783         int input_len;
784         zval *zerror = NULL;
785
786     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|z", &bnf, &bnf_len, &encoding, &input, &input_len, &zerror) == FAILURE) {
787                 RETURN_LONG(-1);
788     }
789     dbex = rpa_dbex_create();
790     if (rpa_dbex_open(dbex) < 0)
791         goto dbexerror;
792     if (rpa_dbex_load(dbex, bnf, bnf_len) < 0)
793         goto dbexerror;
794     rpa_dbex_close(dbex);
795     if (rpa_dbex_compile(dbex) < 0)
796         goto dbexerror;
797     stat = rpa_stat_create(dbex, 16000);
798     ret = rpa_stat_match(stat, rpa_dbex_last(dbex), encoding, input, input, input + input_len);
799     if (ret < 0)
800         goto staterror;
801         if (zerror) {
802                 ZVAL_NULL(zerror);
803         }
804         rpa_stat_destroy(stat);
805         rpa_dbex_destroy(dbex);
806         RETURN_LONG(ret);
807
808 dbexerror:
809         if (zerror) {
810                 rpa_errinfo_t errorinfo;
811                 memset(&errorinfo, 0, sizeof(errorinfo));
812                 rpa_dbex_lasterrorinfo(dbex, &errorinfo);
813                 zval *temp = rpa_zvalerror(&errorinfo);
814                 ZVAL_ZVAL(zerror, temp, 0, 1);
815         }
816         rpa_stat_destroy(stat);
817         rpa_dbex_destroy(dbex);
818         RETURN_LONG(-1);
819
820 staterror:
821         if (zerror) {
822                 rpa_errinfo_t errorinfo;
823                 memset(&errorinfo, 0, sizeof(errorinfo));
824                 rpa_stat_lasterrorinfo(stat, &errorinfo);
825                 zval *temp = rpa_zvalerror(&errorinfo);
826                 ZVAL_ZVAL(zerror, temp, 0, 1);
827         }
828         rpa_stat_destroy(stat);
829         rpa_dbex_destroy(dbex);
830         RETURN_LONG(-1);
831 }
832