RPA Toolkit
d859a83ccd965f192ea58c68da34e03d5c12f153
[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