RPA Toolkit
Fixed config file to use rpatk. Fixed indentation.
[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         REGISTER_LONG_CONSTANT("RPA_E_NONE", RPA_E_NONE, CONST_CS | CONST_PERSISTENT);
161         REGISTER_LONG_CONSTANT("RPA_E_OUTOFMEM", RPA_E_OUTOFMEM, CONST_CS | CONST_PERSISTENT);
162         REGISTER_LONG_CONSTANT("RPA_E_NOTCOMPILED", RPA_E_NOTCOMPILED, CONST_CS | CONST_PERSISTENT);
163         REGISTER_LONG_CONSTANT("RPA_E_NOTOPEN", RPA_E_NOTOPEN, CONST_CS | CONST_PERSISTENT);
164         REGISTER_LONG_CONSTANT("RPA_E_NOTCLOSED", RPA_E_NOTCLOSED, CONST_CS | CONST_PERSISTENT);
165         REGISTER_LONG_CONSTANT("RPA_E_NOTFOUND", RPA_E_NOTFOUND, CONST_CS | CONST_PERSISTENT);
166         REGISTER_LONG_CONSTANT("RPA_E_SYNTAXERROR", RPA_E_SYNTAXERROR, CONST_CS | CONST_PERSISTENT);
167         REGISTER_LONG_CONSTANT("RPA_E_UNRESOLVEDSYMBOL", RPA_E_UNRESOLVEDSYMBOL, CONST_CS | CONST_PERSISTENT);
168         REGISTER_LONG_CONSTANT("RPA_E_PARAM", RPA_E_PARAM, CONST_CS | CONST_PERSISTENT);
169         REGISTER_LONG_CONSTANT("RPA_E_COMPILE", RPA_E_COMPILE, CONST_CS | CONST_PERSISTENT);
170         REGISTER_LONG_CONSTANT("RPA_E_EXECUTION", RPA_E_EXECUTION, CONST_CS | CONST_PERSISTENT);
171         REGISTER_LONG_CONSTANT("RPA_E_USERABORT", RPA_E_USERABORT, CONST_CS | CONST_PERSISTENT);
172         REGISTER_LONG_CONSTANT("RPA_E_RULEABORT", RPA_E_RULEABORT, CONST_CS | CONST_PERSISTENT);
173         REGISTER_LONG_CONSTANT("RPA_E_INVALIDINPUT", RPA_E_INVALIDINPUT, CONST_CS | CONST_PERSISTENT);
174
175         return SUCCESS;
176 }
177 /* }}} */
178
179 /* {{{ PHP_MSHUTDOWN_FUNCTION
180  */
181 PHP_MSHUTDOWN_FUNCTION(prpa)
182 {
183         /* uncomment this line if you have INI entries
184         UNREGISTER_INI_ENTRIES();
185         */
186         return SUCCESS;
187 }
188 /* }}} */
189
190 /* Remove if there's nothing to do at request start */
191 /* {{{ PHP_RINIT_FUNCTION
192  */
193 PHP_RINIT_FUNCTION(prpa)
194 {
195         return SUCCESS;
196 }
197 /* }}} */
198
199 /* Remove if there's nothing to do at request end */
200 /* {{{ PHP_RSHUTDOWN_FUNCTION
201  */
202 PHP_RSHUTDOWN_FUNCTION(prpa)
203 {
204         return SUCCESS;
205 }
206 /* }}} */
207
208 /* {{{ PHP_MINFO_FUNCTION
209  */
210 PHP_MINFO_FUNCTION(prpa)
211 {
212         php_info_print_table_start();
213         php_info_print_table_header(2, "prpa support", "enabled");
214         php_info_print_table_end();
215
216         /* Remove comments if you have entries in php.ini
217         DISPLAY_INI_ENTRIES();
218         */
219 }
220 /* }}} */
221
222
223 PHP_FUNCTION(rpa_dbex_version)
224 {
225         RETURN_STRING((char*)rpa_dbex_version(), 1);
226 }
227
228
229 static void php_rpa_stat_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
230 {
231         php_rpa_stat *phpstat = (php_rpa_stat*)rsrc->ptr;
232
233         if (phpstat) {
234                 rpa_stat_destroy(phpstat->stat);
235                 efree(phpstat);
236         }
237 }
238
239
240 static void php_rpa_dbex_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
241 {
242         php_rpa_dbex *phpdbex = (php_rpa_dbex*)rsrc->ptr;
243
244         if (phpdbex) {
245                 rpa_dbex_destroy(phpdbex->dbex);
246                 efree(phpdbex);
247         }
248 }
249
250
251 PHP_FUNCTION(rpa_dbex_create)
252 {
253         php_rpa_dbex *phpdbex;
254
255         phpdbex = emalloc(sizeof(php_rpa_dbex));
256         phpdbex->dbex = rpa_dbex_create();
257         ZEND_REGISTER_RESOURCE(return_value, phpdbex, le_rpa_dbex);
258 }
259
260
261 PHP_FUNCTION(rpa_dbex_open)
262 {
263         zval *zres;
264         php_rpa_dbex *phpdbex;
265         int ret;
266
267         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
268                 RETURN_LONG(-1);
269         }
270
271         ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
272
273         ret = rpa_dbex_open(phpdbex->dbex);
274         RETURN_LONG(ret);
275 }
276
277
278 PHP_FUNCTION(rpa_dbex_close)
279 {
280         zval *zres;
281         php_rpa_dbex *phpdbex;
282
283         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
284                 RETURN_LONG(-1);
285         }
286
287         ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
288
289         rpa_dbex_close(phpdbex->dbex);
290         RETURN_LONG(0);
291 }
292
293
294 PHP_FUNCTION(rpa_dbex_load)
295 {
296         zval *zres;
297         php_rpa_dbex *phpdbex;
298         char *patterns;
299         int patterns_len;
300         int ret;
301
302
303         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &patterns, &patterns_len) == FAILURE) {
304                 RETURN_LONG(-1);
305         }
306
307         ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
308
309         ret = rpa_dbex_load_s(phpdbex->dbex, patterns);
310         RETURN_LONG(ret);
311 }
312
313
314 PHP_FUNCTION(rpa_dbex_lookup)
315 {
316         zval *zres;
317         php_rpa_dbex *phpdbex;
318         char *name;
319         int name_len;
320         long ret;
321
322         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &name, &name_len) == FAILURE) {
323                 RETURN_LONG(-1);
324         }
325
326         ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
327
328         ret = rpa_dbex_lookup(phpdbex->dbex, name, name_len);
329         RETURN_LONG(ret);
330 }
331
332
333 PHP_FUNCTION(rpa_dbex_first)
334 {
335         zval *zres;
336         php_rpa_dbex *phpdbex;
337         long ret;
338
339         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
340                 RETURN_LONG(-1);
341         }
342
343         ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
344
345         ret = rpa_dbex_first(phpdbex->dbex);
346         RETURN_LONG(ret);
347 }
348
349
350 PHP_FUNCTION(rpa_dbex_last)
351 {
352         zval *zres;
353         php_rpa_dbex *phpdbex;
354         long ret;
355
356         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
357                 RETURN_LONG(-1);
358         }
359         ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
360         ret = rpa_dbex_last(phpdbex->dbex);
361         RETURN_LONG(ret);
362 }
363
364
365 PHP_FUNCTION(rpa_dbex_compile)
366 {
367         zval *zres;
368         php_rpa_dbex *phpdbex;
369         char *patterns;
370         int patterns_len;
371         int 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_compile(phpdbex->dbex);
378         RETURN_LONG(ret);
379 }
380
381
382 PHP_FUNCTION(rpa_dbex_dumpproductions)
383 {
384         zval *zres;
385         php_rpa_dbex *phpdbex;
386         long ret;
387
388         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
389                 RETURN_LONG(-1);
390         }
391         ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
392         ret = rpa_dbex_dumpproductions(phpdbex->dbex);
393         RETURN_LONG(ret);
394 }
395
396
397 PHP_FUNCTION(rpa_dbex_cfgset)
398 {
399         zval *zres;
400         php_rpa_dbex *phpdbex;
401         long cfg, val;
402         long ret;
403
404         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &zres, cfg, val) == FAILURE) {
405                 RETURN_LONG(-1);
406         }
407         ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
408         ret = rpa_dbex_cfgset(phpdbex->dbex, cfg, val);
409         RETURN_LONG(ret);
410 }
411
412
413 static rchar *dbexmsg[] = {
414         "OK",
415         "Out of memory",
416         "Invalid input.",
417         "Expression database is not open.",
418         "Expression database is not closed.",
419         "Expression name is not found.",
420         "Syntax error.",
421         "Unresolved expression name.",
422         "Invalid parameter.",
423         "Failed to compile rule.",
424         "Database is not compiled.",
425         "Unknown",
426         "Unknown",
427         "Unknown",
428         "Unknown",
429         "Unknown",
430         "Unknown",
431         "Unknown",
432 };
433
434
435 static rchar *statmsg[] = {
436         "OK",
437         "Execution error.",
438         "Execution aborted by user.",
439         "Aborted on expression.",
440         "Unknown",
441         "Unknown",
442         "Unknown",
443         "Unknown",
444         "Unknown",
445         "Unknown",
446         "Unknown",
447 };
448
449
450 static zval *rpa_zvalerror(rpa_errinfo_t *errorinfo)
451 {
452         long n = 0;
453         char buffer[1000];
454         char *ptr = buffer;
455         size_t size = sizeof(buffer) - 1;
456         zval *zerror = NULL;
457
458         memset(buffer, 0, sizeof(buffer));
459         ALLOC_INIT_ZVAL(zerror);
460         array_init(zerror);
461         if (errorinfo->mask & RPA_ERRINFO_CODE) {
462                 if (errorinfo->code >= 1000 && errorinfo->code < 1010)
463                         n += snprintf(ptr + n, size - n, "%s Code: %ld. ", dbexmsg[errorinfo->code - 1000], errorinfo->code);
464                 else if (errorinfo->code >= 2000 && errorinfo->code < 2010)
465                         n += snprintf(ptr + n, size - n, "%s Code: %ld. ", statmsg[errorinfo->code - 2000], errorinfo->code);
466                 else
467                         n += snprintf(ptr + n, size - n, "Error Code: %ld. ", errorinfo->code);
468                 add_assoc_long(zerror, "code", errorinfo->code);
469         }
470         if (errorinfo->mask & RPA_ERRINFO_LINE) {
471                 n += snprintf(ptr + n, size - n, "Line: %ld. ", errorinfo->line);
472                 add_assoc_long(zerror, "line", errorinfo->line);
473         }
474         if (errorinfo->mask & RPA_ERRINFO_OFFSET) {
475                 n += snprintf(ptr + n, size - n, "Offset: %ld. ", errorinfo->offset);
476                 add_assoc_long(zerror, "offset", errorinfo->offset);
477         }
478         if (errorinfo->mask & RPA_ERRINFO_RULEID) {
479                 n += snprintf(ptr + n, size - n, "RuleId: %ld. ", errorinfo->ruleid);
480                 add_assoc_long(zerror, "rid", errorinfo->ruleid);
481         }
482         if (errorinfo->mask & RPA_ERRINFO_NAME) {
483                 n += snprintf(ptr + n, size - n, "Name: %s. ", errorinfo->name);
484                 add_assoc_string(zerror, "name", errorinfo->name, 1);
485         }
486         add_assoc_stringl(zerror, "message", buffer, n, 1);
487         return zerror;
488 }
489
490
491 PHP_FUNCTION(rpa_dbex_error)
492 {
493         zval *zres;
494         php_rpa_dbex *phpdbex;
495         zval *zerror = NULL;
496         rpa_errinfo_t errorinfo;
497
498         memset(&errorinfo, 0, sizeof(errorinfo));
499         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
500                 RETURN_LONG(-1);
501         }
502         ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
503         rpa_dbex_lasterrorinfo(phpdbex->dbex, &errorinfo);
504         zerror = rpa_zvalerror(&errorinfo);
505         RETURN_ZVAL(zerror, 1, 0);
506 }
507
508
509 PHP_FUNCTION(rpa_stat_error)
510 {
511         zval *zres;
512         char buffer[1000];
513         php_rpa_stat *phpstat;
514         zval *zerror = NULL;
515         rpa_errinfo_t errorinfo;
516
517         memset(&errorinfo, 0, sizeof(errorinfo));
518         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
519                 RETURN_LONG(-1);
520         }
521         ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zres, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
522         rpa_stat_lasterrorinfo(phpstat->stat, &errorinfo);
523         zerror = rpa_zvalerror(&errorinfo);
524         RETURN_ZVAL(zerror, 1, 0);
525 }
526
527
528 static void rpa_records2array(const rchar *input, rarray_t *records, zval *zrecords)
529 {
530         rlong i;
531
532         rparecord_t *record;
533         array_init(zrecords);
534         for (i = 0; i < rpa_records_length(records); i++) {
535                 zval *zrecord;
536                 record = rpa_records_slot(records, i);
537                 ALLOC_INIT_ZVAL(zrecord);
538                 array_init(zrecord);
539                 add_assoc_stringl(zrecord, "input", (char*)record->input, record->inputsiz, 1);
540                 add_assoc_string(zrecord, "rule", (char*)record->rule, 1);
541                 add_assoc_long(zrecord, "type", record->type);
542                 add_assoc_long(zrecord, "uid", record->ruleuid);
543                 add_assoc_long(zrecord, "offset", record->input - input);
544                 add_assoc_long(zrecord, "size", record->inputsiz);
545                 add_next_index_zval(zrecords, zrecord);
546         }
547 }
548
549
550 PHP_FUNCTION(rpa_stat_create)
551 {
552         zval *zres;
553         php_rpa_dbex *phpdbex;
554         php_rpa_stat *phpstat;
555         int ret;
556         long stackSize = 0L;
557
558         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zres, &stackSize) == FAILURE) {
559                 RETURN_LONG(-1);
560         }
561         ZEND_FETCH_RESOURCE(phpdbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
562         phpstat = emalloc(sizeof(php_rpa_stat));
563         phpstat->stat = rpa_stat_create(phpdbex->dbex, stackSize);
564         ZEND_REGISTER_RESOURCE(return_value, phpstat, le_rpa_stat);
565 }
566
567
568 PHP_FUNCTION(rpa_stat_match)
569 {
570         zval *zstat;
571         php_rpa_stat *phpstat;
572         long rid;
573         long encoding;
574         long ret;
575         char *input;
576         int input_len;
577
578         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlls", &zstat, &rid, &encoding, &input, &input_len) == FAILURE) {
579                 RETURN_LONG(-1);
580         }
581         ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zstat, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
582         ret = rpa_stat_match(phpstat->stat, rid, encoding, input, input, input + input_len);
583         RETURN_LONG(ret);
584 }
585
586
587 PHP_FUNCTION(rpa_stat_scan)
588 {
589         zval *zstat;
590         php_rpa_stat *phpstat;
591         long rid;
592         long encoding;
593         long ret;
594         char *input;
595         int input_len;
596         zval *zwhere;
597         const char *where = NULL;
598
599         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllsz", &zstat, &rid, &encoding, &input, &input_len, &zwhere) == FAILURE) {
600                 RETURN_LONG(-1);
601         }
602         ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zstat, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
603         ret = rpa_stat_scan(phpstat->stat, rid, encoding, input, input, input + input_len, &where);
604         if (ret > 0) {
605                 ZVAL_LONG(zwhere, where - input);
606         } else {
607                 ZVAL_NULL(zwhere);
608         }
609         RETURN_LONG(ret);
610 }
611
612
613 PHP_FUNCTION(rpa_stat_parse)
614 {
615         zval *zstat;
616         php_rpa_stat *phpstat;
617         long rid;
618         long encoding;
619         long ret, i;
620         char *input;
621         int input_len;
622         zval *zrecords = NULL;
623         rarray_t *records = rpa_records_create();
624
625         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlls|z", &zstat, &rid, &encoding, &input, &input_len, &zrecords) == FAILURE) {
626                 RETURN_LONG(-1);
627         }
628         ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zstat, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
629         ret = rpa_stat_parse(phpstat->stat, rid, encoding, input, input, input + input_len, records);
630         if (ret <= 0) {
631                 if (zrecords)
632                         ZVAL_NULL(zrecords);
633                 rpa_records_destroy(records);
634                 RETURN_LONG(ret);
635         }
636         if (zrecords) {
637                 rpa_records2array(input, records, zrecords);
638         }
639         rpa_records_destroy(records);
640         RETURN_LONG(ret);
641 }
642
643
644 PHP_FUNCTION(rpaparse)
645 {
646         rpadbex_t *dbex = NULL;
647         rpastat_t *stat = NULL;
648         long rid;
649         long encoding;
650         long ret, i;
651         char *bnf;
652         int bnf_len;
653         char *input;
654         int input_len;
655         zval *zerror = NULL;
656         zval *zrecords = NULL;
657         rarray_t *records = rpa_records_create();
658
659         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|zz", &bnf, &bnf_len, &encoding, &input, &input_len, &zrecords, &zerror) == FAILURE) {
660                 RETURN_LONG(-1);
661         }
662         dbex = rpa_dbex_create();
663         if (rpa_dbex_open(dbex) < 0)
664                 goto dbexerror;
665         if (rpa_dbex_load(dbex, bnf, bnf_len) < 0)
666                 goto dbexerror;
667         rpa_dbex_close(dbex);
668         if (rpa_dbex_compile(dbex) < 0)
669                 goto dbexerror;
670         stat = rpa_stat_create(dbex, 16000);
671         ret = rpa_stat_parse(stat, rpa_dbex_last(dbex), encoding, input, input, input + input_len, records);
672         if (ret < 0)
673                 goto staterror;
674         if (ret > 0 && zrecords) {
675                 rpa_records2array(input, records, zrecords);
676         }
677
678         if (zerror) {
679                 ZVAL_NULL(zerror);
680         }
681         rpa_records_destroy(records);
682         rpa_stat_destroy(stat);
683         rpa_dbex_destroy(dbex);
684         RETURN_LONG(ret);
685
686 dbexerror:
687         if (zerror) {
688                 rpa_errinfo_t errorinfo;
689                 memset(&errorinfo, 0, sizeof(errorinfo));
690                 rpa_dbex_lasterrorinfo(dbex, &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 staterror:
702         if (zerror) {
703                 rpa_errinfo_t errorinfo;
704                 memset(&errorinfo, 0, sizeof(errorinfo));
705                 rpa_stat_lasterrorinfo(stat, &errorinfo);
706                 zval *temp = rpa_zvalerror(&errorinfo);
707                 ZVAL_ZVAL(zerror, temp, 0, 1);
708         }
709 //      if (zrecords)
710 //              ZVAL_NULL(zrecords);
711         rpa_records_destroy(records);
712         rpa_stat_destroy(stat);
713         rpa_dbex_destroy(dbex);
714         RETURN_LONG(-1);
715 }
716
717
718 PHP_FUNCTION(rpascan)
719 {
720         rpadbex_t *dbex = NULL;
721         rpastat_t *stat = NULL;
722         long rid;
723         long encoding;
724         long ret, i;
725         char *bnf;
726         int bnf_len;
727         char *input;
728         const rchar *where = NULL;
729         int input_len;
730         zval *zerror = NULL;
731         zval *zwhere = NULL;
732
733         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|zz", &bnf, &bnf_len, &encoding, &input, &input_len, &zwhere, &zerror) == FAILURE) {
734                 RETURN_LONG(-1);
735         }
736         dbex = rpa_dbex_create();
737         if (rpa_dbex_open(dbex) < 0)
738                 goto dbexerror;
739         if (rpa_dbex_load(dbex, bnf, bnf_len) < 0)
740                 goto dbexerror;
741         rpa_dbex_close(dbex);
742         if (rpa_dbex_compile(dbex) < 0)
743                 goto dbexerror;
744         stat = rpa_stat_create(dbex, 16000);
745         ret = rpa_stat_scan(stat, rpa_dbex_last(dbex), encoding, input, input, input + input_len, &where);
746         if (ret < 0)
747                 goto staterror;
748         if (zwhere) {
749                 if (ret > 0 && where) {
750                         ZVAL_LONG(zwhere, where - input);
751                 } else {
752                         ZVAL_NULL(zwhere);
753                 }
754         }
755         if (zerror) {
756                 ZVAL_NULL(zerror);
757         }
758         rpa_stat_destroy(stat);
759         rpa_dbex_destroy(dbex);
760         RETURN_LONG(ret);
761
762 dbexerror:
763         if (zerror) {
764                 rpa_errinfo_t errorinfo;
765                 memset(&errorinfo, 0, sizeof(errorinfo));
766                 rpa_dbex_lasterrorinfo(dbex, &errorinfo);
767                 zval *temp = rpa_zvalerror(&errorinfo);
768                 ZVAL_ZVAL(zerror, temp, 0, 1);
769         }
770         rpa_stat_destroy(stat);
771         rpa_dbex_destroy(dbex);
772         RETURN_LONG(-1);
773
774 staterror:
775         if (zerror) {
776                 rpa_errinfo_t errorinfo;
777                 memset(&errorinfo, 0, sizeof(errorinfo));
778                 rpa_stat_lasterrorinfo(stat, &errorinfo);
779                 zval *temp = rpa_zvalerror(&errorinfo);
780                 ZVAL_ZVAL(zerror, temp, 0, 1);
781         }
782         rpa_stat_destroy(stat);
783         rpa_dbex_destroy(dbex);
784         RETURN_LONG(-1);
785 }
786
787
788 PHP_FUNCTION(rpamatch)
789 {
790         rpadbex_t *dbex = NULL;
791         rpastat_t *stat = NULL;
792         long rid;
793         long encoding;
794         long ret, i;
795         char *bnf;
796         int bnf_len;
797         char *input;
798         int input_len;
799         zval *zerror = NULL;
800
801         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|z", &bnf, &bnf_len, &encoding, &input, &input_len, &zerror) == FAILURE) {
802                 RETURN_LONG(-1);
803         }
804         dbex = rpa_dbex_create();
805         if (rpa_dbex_open(dbex) < 0)
806                 goto dbexerror;
807         if (rpa_dbex_load(dbex, bnf, bnf_len) < 0)
808                 goto dbexerror;
809         rpa_dbex_close(dbex);
810         if (rpa_dbex_compile(dbex) < 0)
811                 goto dbexerror;
812         stat = rpa_stat_create(dbex, 16000);
813         ret = rpa_stat_match(stat, rpa_dbex_last(dbex), encoding, input, input, input + input_len);
814         if (ret < 0)
815                 goto staterror;
816         if (zerror) {
817                 ZVAL_NULL(zerror);
818         }
819         rpa_stat_destroy(stat);
820         rpa_dbex_destroy(dbex);
821         RETURN_LONG(ret);
822
823 dbexerror:
824         if (zerror) {
825                 rpa_errinfo_t errorinfo;
826                 memset(&errorinfo, 0, sizeof(errorinfo));
827                 rpa_dbex_lasterrorinfo(dbex, &errorinfo);
828                 zval *temp = rpa_zvalerror(&errorinfo);
829                 ZVAL_ZVAL(zerror, temp, 0, 1);
830         }
831         rpa_stat_destroy(stat);
832         rpa_dbex_destroy(dbex);
833         RETURN_LONG(-1);
834
835 staterror:
836         if (zerror) {
837                 rpa_errinfo_t errorinfo;
838                 memset(&errorinfo, 0, sizeof(errorinfo));
839                 rpa_stat_lasterrorinfo(stat, &errorinfo);
840                 zval *temp = rpa_zvalerror(&errorinfo);
841                 ZVAL_ZVAL(zerror, temp, 0, 1);
842         }
843         rpa_stat_destroy(stat);
844         rpa_dbex_destroy(dbex);
845         RETURN_LONG(-1);
846 }
847