1 /**
2  * The MeCab PHP extension
3  *
4  * Copyright (c) 2006-2015 Ryusuke SEKIYAMA. All rights reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * @package     php-mecab
25  * @author      Ryusuke SEKIYAMA <rsky0711@gmail.com>
26  * @copyright   2006-2015 Ryusuke SEKIYAMA
27  * @license     http://www.opensource.org/licenses/mit-license.php  MIT License
28  * @version     $Id$
29  */
30 
31 #include "php_mecab.h"
32 #include "php_mecab_compat5.h"
33 
34 #define PATHBUFSIZE (MAXPATHLEN + 3)
35 
36 /* {{{ globals */
37 
38 static ZEND_DECLARE_MODULE_GLOBALS(mecab)
39 
40 static int le_mecab;
41 static int le_mecab_node;
42 static int le_mecab_path;
43 
44 /* }}} */
45 
46 /* {{{ class entries */
47 
48 static zend_class_entry *ext_ce_Iterator;
49 static zend_class_entry *ext_ce_IteratorAggregate;
50 static zend_class_entry *ext_ce_BadMethodCallException;
51 static zend_class_entry *ext_ce_InvalidArgumentException;
52 static zend_class_entry *ext_ce_OutOfRangeException;
53 
54 static zend_class_entry *ce_MeCab_Tagger = NULL;
55 static zend_class_entry *ce_MeCab_Node = NULL;
56 static zend_class_entry *ce_MeCab_NodeIterator = NULL;
57 static zend_class_entry *ce_MeCab_Path = NULL;
58 
59 static zend_class_entry *ce_MeCab_Deprecated = NULL;
60 static zend_class_entry *ce_MeCab_Tagger_Deprecated = NULL;
61 static zend_class_entry *ce_MeCab_Node_Deprecated = NULL;
62 static zend_class_entry *ce_MeCab_Path_Deprecated = NULL;
63 
64 static zend_object_handlers php_mecab_object_handlers;
65 static zend_object_handlers php_mecab_node_object_handlers;
66 static zend_object_handlers php_mecab_path_object_handlers;
67 
68 /* }}} */
69 
70 /* {{{ module function prototypes */
71 
72 static PHP_MINIT_FUNCTION(mecab);
73 static PHP_MSHUTDOWN_FUNCTION(mecab);
74 static PHP_MINFO_FUNCTION(mecab);
75 static PHP_GINIT_FUNCTION(mecab);
76 
77 /* }}} */
78 
79 /* {{{ PHP function prototypes */
80 
81 /* Get MeCab library version */
82 static PHP_FUNCTION(mecab_version);
83 /* Wakati-Gaki function */
84 static PHP_FUNCTION(mecab_split);
85 /* MeCab API wrappers */
86 static PHP_FUNCTION(mecab_new);
87 static PHP_FUNCTION(mecab_destroy);
88 static PHP_FUNCTION(mecab_get_partial);
89 static PHP_FUNCTION(mecab_set_partial);
90 static PHP_FUNCTION(mecab_get_theta);
91 static PHP_FUNCTION(mecab_set_theta);
92 static PHP_FUNCTION(mecab_get_lattice_level);
93 static PHP_FUNCTION(mecab_set_lattice_level);
94 static PHP_FUNCTION(mecab_get_all_morphs);
95 static PHP_FUNCTION(mecab_set_all_morphs);
96 static PHP_FUNCTION(mecab_sparse_tostr);
97 static PHP_FUNCTION(mecab_sparse_tonode);
98 static PHP_FUNCTION(mecab_nbest_sparse_tostr);
99 static PHP_FUNCTION(mecab_nbest_init);
100 static PHP_FUNCTION(mecab_nbest_next_tostr);
101 static PHP_FUNCTION(mecab_nbest_next_tonode);
102 static PHP_FUNCTION(mecab_format_node);
103 static PHP_FUNCTION(mecab_dictionary_info);
104 /* Dumper for mecab_node */
105 static PHP_FUNCTION(mecab_node_toarray);
106 static PHP_FUNCTION(mecab_node_tostring);
107 /* Getters for mecab_node */
108 static PHP_FUNCTION(mecab_node_prev);
109 static PHP_FUNCTION(mecab_node_next);
110 static PHP_FUNCTION(mecab_node_enext);
111 static PHP_FUNCTION(mecab_node_bnext);
112 static PHP_FUNCTION(mecab_node_rpath);
113 static PHP_FUNCTION(mecab_node_lpath);
114 static PHP_FUNCTION(mecab_node_surface);
115 static PHP_FUNCTION(mecab_node_feature);
116 static PHP_FUNCTION(mecab_node_id);
117 static PHP_FUNCTION(mecab_node_length);
118 static PHP_FUNCTION(mecab_node_rlength);
119 static PHP_FUNCTION(mecab_node_rcattr);
120 static PHP_FUNCTION(mecab_node_lcattr);
121 static PHP_FUNCTION(mecab_node_posid);
122 static PHP_FUNCTION(mecab_node_char_type);
123 static PHP_FUNCTION(mecab_node_stat);
124 static PHP_FUNCTION(mecab_node_isbest);
125 static PHP_FUNCTION(mecab_node_alpha);
126 static PHP_FUNCTION(mecab_node_beta);
127 static PHP_FUNCTION(mecab_node_prob);
128 static PHP_FUNCTION(mecab_node_wcost);
129 static PHP_FUNCTION(mecab_node_cost);
130 /* Getters for mecab_path */
131 static PHP_FUNCTION(mecab_path_rnext);
132 static PHP_FUNCTION(mecab_path_lnext);
133 static PHP_FUNCTION(mecab_path_rnode);
134 static PHP_FUNCTION(mecab_path_lnode);
135 static PHP_FUNCTION(mecab_path_prob);
136 static PHP_FUNCTION(mecab_path_cost);
137 
138 /* }}} */
139 
140 /* {{{ PHP method prototypes */
141 
142 static PHP_METHOD(MeCab_Node, __construct);
143 static PHP_METHOD(MeCab_Path, __construct);
144 /* Overloading implementations for mecab_node */
145 static PHP_METHOD(MeCab_Node, __get);
146 static PHP_METHOD(MeCab_Node, __isset);
147 /* IteratorAggregate implementations for mecab_node */
148 static PHP_METHOD(MeCab_Node, getIterator);
149 static PHP_METHOD(MeCab_Node, setTraverse);
150 /* Iterator implementations for mecab_node */
151 static PHP_METHOD(MeCab_NodeIterator, __construct);
152 static PHP_METHOD(MeCab_NodeIterator, current);
153 static PHP_METHOD(MeCab_NodeIterator, key);
154 static PHP_METHOD(MeCab_NodeIterator, valid);
155 static PHP_METHOD(MeCab_NodeIterator, rewind);
156 static PHP_METHOD(MeCab_NodeIterator, next);
157 /* Overloading implementations for mecab_path */
158 static PHP_METHOD(MeCab_Path, __get);
159 static PHP_METHOD(MeCab_Path, __isset);
160 
161 /* }}} */
162 
163 /* {{{ internal function prototypes */
164 
165 /* allocate for mecab */
166 static php_mecab *
167 php_mecab_ctor(TSRMLS_D);
168 
169 /* free the mecab */
170 static void
171 php_mecab_dtor(php_mecab *mecab TSRMLS_DC);
172 
173 /* free the mecab resource */
174 static void
175 php_mecab_free_resource(zend_rsrc_list_entry *rsrc TSRMLS_DC);
176 
177 /* set string to the mecab */
178 static void
179 php_mecab_set_string(php_mecab *mecab, const char *str, int len TSRMLS_DC);
180 
181 /* allocate for mecab_node */
182 static php_mecab_node *
183 php_mecab_node_ctor(TSRMLS_D);
184 
185 /* free the mecab_node */
186 static void
187 php_mecab_node_dtor(php_mecab_node *node TSRMLS_DC);
188 
189 /* free the mecab_node resource */
190 static void
191 php_mecab_node_free_resource(zend_rsrc_list_entry *rsrc TSRMLS_DC);
192 
193 /* set mecab to the mecab_node */
194 static void
195 php_mecab_node_set_tagger(php_mecab_node *node, php_mecab *mecab TSRMLS_DC);
196 
197 /* allocate for mecab_path */
198 static php_mecab_path *
199 php_mecab_path_ctor(TSRMLS_D);
200 
201 /* free the mecab_path */
202 static void
203 php_mecab_path_dtor(php_mecab_path *path TSRMLS_DC);
204 
205 /* free the mecab_path resource */
206 static void
207 php_mecab_path_free_resource(zend_rsrc_list_entry *rsrc TSRMLS_DC);
208 
209 /* set mecab_node to the mecab_path */
210 static void
211 php_mecab_path_set_tagger(php_mecab_path *path, php_mecab *mecab TSRMLS_DC);
212 
213 /* get sibling node from mecab_node */
214 static zval *
215 php_mecab_node_get_sibling(zval *zv, zval *object, php_mecab_node *xnode, php_mecab_node_rel rel TSRMLS_DC);
216 
217 /* get related path from mecab_node */
218 static zval *
219 php_mecab_node_get_path(zval *zv, zval *object, php_mecab_node *xnode, php_mecab_node_rel rel TSRMLS_DC);
220 
221 /* get sibling path from mecab_path */
222 static zval *
223 php_mecab_path_get_sibling(zval *zv, zval *object, php_mecab_path *xpath, php_mecab_path_rel rel TSRMLS_DC);
224 
225 /* get related node from mecab_path */
226 static zval *
227 php_mecab_path_get_node(zval *zv, zval *object, php_mecab_path *xpath, php_mecab_path_rel rel TSRMLS_DC);
228 
229 /* wrappers */
230 static void
231 php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_node_rel rel),
232 php_mecab_node_get_path_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_node_rel rel),
233 php_mecab_path_get_sibling_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_path_rel rel),
234 php_mecab_path_get_node_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_path_rel rel);
235 
236 /* allocate for mecab object */
237 zend_object_value
238 php_mecab_object_new(zend_class_entry *ce TSRMLS_DC);
239 
240 /* free the mecab object */
241 static void
242 php_mecab_free_object_storage(void *object TSRMLS_DC);
243 
244 /* allocate for mecab_node object */
245 zend_object_value
246 php_mecab_node_object_new(zend_class_entry *ce TSRMLS_DC);
247 
248 /* free the mecab_node object */
249 static void
250 php_mecab_node_free_object_storage(void *object TSRMLS_DC);
251 
252 /* allocate for mecab_path object */
253 zend_object_value
254 php_mecab_path_object_new(zend_class_entry *ce TSRMLS_DC);
255 
256 /* free the mecab_path object */
257 static void
258 php_mecab_path_free_object_storage(void *object TSRMLS_DC);
259 
260 /* get the class entry */
261 static zend_class_entry *
262 php_mecab_get_class_entry(const char *lcname TSRMLS_DC);
263 
264 /* }}} */
265 
266 /* check file/dicectory accessibility */
267 static zend_bool
268 php_mecab_check_path(const char *path, size_t length, char *real_path TSRMLS_DC);
269 
270 /* }}} */
271 
272 /* {{{ argument informations */
273 
274 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab__mecab, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
275 	ZEND_ARG_INFO(0, mecab)
276 ZEND_END_ARG_INFO()
277 
278 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_split, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
279 	ZEND_ARG_INFO(0, str)
280 	ZEND_ARG_INFO(0, dicdir)
281 	ZEND_ARG_INFO(0, userdic)
282 ZEND_END_ARG_INFO()
283 
284 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_new, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
285 	ZEND_ARG_ARRAY_INFO(0, arg, 1)
286 ZEND_END_ARG_INFO()
287 
288 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_set_partial, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
289 	ZEND_ARG_INFO(0, mecab)
290 	ZEND_ARG_INFO(0, partial)
291 ZEND_END_ARG_INFO()
292 
293 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_set_partial_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
294 	ZEND_ARG_INFO(0, partial)
295 ZEND_END_ARG_INFO()
296 
297 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_set_theta, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
298 	ZEND_ARG_INFO(0, mecab)
299 	ZEND_ARG_INFO(0, theta)
300 ZEND_END_ARG_INFO()
301 
302 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_set_theta_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
303 	ZEND_ARG_INFO(0, theta)
304 ZEND_END_ARG_INFO()
305 
306 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_set_lattice_level, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
307 	ZEND_ARG_INFO(0, mecab)
308 	ZEND_ARG_INFO(0, level)
309 ZEND_END_ARG_INFO()
310 
311 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_set_lattice_level_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
312 	ZEND_ARG_INFO(0, level)
313 ZEND_END_ARG_INFO()
314 
315 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_set_all_morphs, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
316 	ZEND_ARG_INFO(0, mecab)
317 	ZEND_ARG_INFO(0, all_morphs)
318 ZEND_END_ARG_INFO()
319 
320 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_set_all_morphs_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
321 	ZEND_ARG_INFO(0, all_morphs)
322 ZEND_END_ARG_INFO()
323 
324 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_sparse_tostr, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 2)
325 	ZEND_ARG_INFO(0, mecab)
326 	ZEND_ARG_INFO(0, str)
327 	ZEND_ARG_INFO(0, len)
328 	ZEND_ARG_INFO(0, olen)
329 ZEND_END_ARG_INFO()
330 
331 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_sparse_tostr_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
332 	ZEND_ARG_INFO(0, str)
333 	ZEND_ARG_INFO(0, len)
334 	ZEND_ARG_INFO(0, olen)
335 ZEND_END_ARG_INFO()
336 
337 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_sparse_tonode, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 2)
338 	ZEND_ARG_INFO(0, mecab)
339 	ZEND_ARG_INFO(0, str)
340 	ZEND_ARG_INFO(0, len)
341 ZEND_END_ARG_INFO()
342 
343 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_sparse_tonode_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
344 	ZEND_ARG_INFO(0, str)
345 	ZEND_ARG_INFO(0, len)
346 ZEND_END_ARG_INFO()
347 
348 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_nbest_sparse_tostr, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 3)
349 	ZEND_ARG_INFO(0, mecab)
350 	ZEND_ARG_INFO(0, n)
351 	ZEND_ARG_INFO(0, str)
352 	ZEND_ARG_INFO(0, len)
353 	ZEND_ARG_INFO(0, olen)
354 ZEND_END_ARG_INFO()
355 
356 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_nbest_sparse_tostr_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 2)
357 	ZEND_ARG_INFO(0, n)
358 	ZEND_ARG_INFO(0, str)
359 	ZEND_ARG_INFO(0, len)
360 	ZEND_ARG_INFO(0, olen)
361 ZEND_END_ARG_INFO()
362 
363 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_nbest_init, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 2)
364 	ZEND_ARG_INFO(0, mecab)
365 	ZEND_ARG_INFO(0, str)
366 	ZEND_ARG_INFO(0, len)
367 ZEND_END_ARG_INFO()
368 
369 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_nbest_init_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
370 	ZEND_ARG_INFO(0, str)
371 	ZEND_ARG_INFO(0, len)
372 ZEND_END_ARG_INFO()
373 
374 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_nbest_next_tostr, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
375 	ZEND_ARG_INFO(0, mecab)
376 	ZEND_ARG_INFO(0, olen)
377 ZEND_END_ARG_INFO()
378 
379 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_nbest_next_tostr_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
380 	ZEND_ARG_INFO(0, olen)
381 ZEND_END_ARG_INFO()
382 
383 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_format_node, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
384 	ZEND_ARG_INFO(0, mecab)
385 	ZEND_ARG_INFO(0, node)
386 ZEND_END_ARG_INFO()
387 
388 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_format_node_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
389 	ZEND_ARG_OBJ_INFO(0, node, MeCab_Node, 0)
390 ZEND_END_ARG_INFO()
391 
392 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_node__node, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
393 	ZEND_ARG_INFO(0, node)
394 ZEND_END_ARG_INFO()
395 
396 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_node_toarray, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
397 	ZEND_ARG_INFO(0, node)
398 	ZEND_ARG_INFO(0, dump_all)
399 ZEND_END_ARG_INFO()
400 
401 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_node_toarray_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
402 	ZEND_ARG_INFO(0, dump_all)
403 ZEND_END_ARG_INFO()
404 
405 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_node_settraverse, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
406 	ZEND_ARG_INFO(0, traverse)
407 ZEND_END_ARG_INFO()
408 
409 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_path__path, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
410 	ZEND_ARG_INFO(0, path)
411 ZEND_END_ARG_INFO()
412 
413 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab__magic_getter, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
414 	ZEND_ARG_INFO(0, name)
415 ZEND_END_ARG_INFO()
416 
417 /* }}} arginfo */
418 
419 /* {{{ MeCab methods[] */
420 #define PM_TAGGER_ME_MAPPING(methname, funcname) \
421 	PHP_ME_MAPPING(methname, mecab_ ## funcname, NULL, ZEND_ACC_PUBLIC)
422 
423 #define PM_TAGGER_ME_MAPPING_EX(methname, funcname) \
424 	PHP_ME_MAPPING(methname, mecab_ ## funcname, arginfo_mecab_ ## funcname ## _m, ZEND_ACC_PUBLIC)
425 
426 static zend_function_entry mecab_methods[] = {
427 	/* MeCab API wrappers */
428 	PHP_ME_MAPPING(__construct, mecab_new,   arginfo_mecab_new, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
429 	PM_TAGGER_ME_MAPPING(getPartial,         get_partial)
430 	PM_TAGGER_ME_MAPPING_EX(setPartial,      set_partial)
431 	PM_TAGGER_ME_MAPPING(getTheta,           get_theta)
432 	PM_TAGGER_ME_MAPPING_EX(setTheta,        set_theta)
433 	PM_TAGGER_ME_MAPPING(getLatticeLevel,    get_lattice_level)
434 	PM_TAGGER_ME_MAPPING_EX(setLatticeLevel, set_lattice_level)
435 	PM_TAGGER_ME_MAPPING(getAllMorphs,       get_all_morphs)
436 	PM_TAGGER_ME_MAPPING_EX(setAllMorphs,    set_all_morphs)
437 	PM_TAGGER_ME_MAPPING_EX(parse,           sparse_tostr)
438 	PM_TAGGER_ME_MAPPING_EX(parseToString,   sparse_tostr)
439 	PM_TAGGER_ME_MAPPING_EX(parseToNode,     sparse_tonode)
440 	PM_TAGGER_ME_MAPPING_EX(parseNBest,      nbest_sparse_tostr)
441 	PM_TAGGER_ME_MAPPING_EX(parseNBestInit,  nbest_init)
442 	PM_TAGGER_ME_MAPPING_EX(next,            nbest_next_tostr)
443 	PM_TAGGER_ME_MAPPING(nextNode,           nbest_next_tonode)
444 	PM_TAGGER_ME_MAPPING_EX(formatNode,      format_node)
445 	PM_TAGGER_ME_MAPPING(dictionaryInfo,     dictionary_info)
446 	PHP_FE_END
447 };
448 
449 static zend_function_entry mecab_deprecated_methods[] = {
450 	PHP_ME_MAPPING(version,     mecab_version, NULL,                ZEND_ACC_PUBLIC | ZEND_ACC_STATIC | ZEND_ACC_DEPRECATED)
451 	PHP_ME_MAPPING(split,       mecab_split,   arginfo_mecab_split, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC | ZEND_ACC_DEPRECATED)
452 	PHP_ME_MAPPING(__construct, mecab_new,     arginfo_mecab_new,   ZEND_ACC_PUBLIC | ZEND_ACC_CTOR | ZEND_ACC_DEPRECATED)
453 	PHP_FE_END
454 };
455 /* }}} */
456 
457 /* {{{ MeCab_Node methods[] */
458 #define PM_NODE_ME_MAPPING(methname, funcname) \
459 	PHP_ME_MAPPING(methname, mecab_node_ ## funcname, NULL, ZEND_ACC_PUBLIC)
460 
461 static zend_function_entry mecab_node_methods[] = {
462 	/* Constructor */
463 	PHP_ME(MeCab_Node, __construct, NULL, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
464 	/* Overloading implementations */
465 	PHP_ME(MeCab_Node, __get,   arginfo_mecab__magic_getter, ZEND_ACC_PUBLIC)
466 	PHP_ME(MeCab_Node, __isset, arginfo_mecab__magic_getter, ZEND_ACC_PUBLIC)
467 	/* IteratorAggregate implementations */
468 	PHP_ME(MeCab_Node, getIterator, NULL, ZEND_ACC_PUBLIC)
469 	PHP_ME(MeCab_Node, setTraverse, arginfo_mecab_node_settraverse, ZEND_ACC_PUBLIC)
470 	/* Dumper */
471 	PHP_ME_MAPPING(toArray, mecab_node_toarray, arginfo_mecab_node_toarray_m, ZEND_ACC_PUBLIC)
472 	PM_NODE_ME_MAPPING(toString, tostring)
473 	PM_NODE_ME_MAPPING(__toString, tostring)
474 	/* Getters */
475 	PM_NODE_ME_MAPPING(getPrev,     prev)
476 	PM_NODE_ME_MAPPING(getNext,     next)
477 	PM_NODE_ME_MAPPING(getENext,    enext)
478 	PM_NODE_ME_MAPPING(getBNext,    bnext)
479 	PM_NODE_ME_MAPPING(getRPath,    rpath)
480 	PM_NODE_ME_MAPPING(getLPath,    lpath)
481 	PM_NODE_ME_MAPPING(getSurface,  surface)
482 	PM_NODE_ME_MAPPING(getFeature,  feature)
483 	PM_NODE_ME_MAPPING(getId,       id)
484 	PM_NODE_ME_MAPPING(getLength,   length)
485 	PM_NODE_ME_MAPPING(getRLength,  rlength)
486 	PM_NODE_ME_MAPPING(getRcAttr,   rcattr)
487 	PM_NODE_ME_MAPPING(getLcAttr,   lcattr)
488 	PM_NODE_ME_MAPPING(getPosId,    posid)
489 	PM_NODE_ME_MAPPING(getCharType, char_type)
490 	PM_NODE_ME_MAPPING(getStat,     stat)
491 	PM_NODE_ME_MAPPING(isBest,      isbest)
492 	PM_NODE_ME_MAPPING(getAlpha,    alpha)
493 	PM_NODE_ME_MAPPING(getBeta,     beta)
494 	PM_NODE_ME_MAPPING(getProb,     prob)
495 	PM_NODE_ME_MAPPING(getWCost,    wcost)
496 	PM_NODE_ME_MAPPING(getCost,     cost)
497 	PHP_FE_END
498 };
499 
500 static zend_function_entry mecab_node_deprecated_methods[] = {
501 	PHP_ME(MeCab_Node, __construct, NULL, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR | ZEND_ACC_DEPRECATED)
502 	PHP_FE_END
503 };
504 /* }}} */
505 
506 /* {{{ MeCab_NodeIterator methods[] */
507 static zend_function_entry mecab_iterator_methods[] = {
508 	/* Constructor */
509 	PHP_ME(MeCab_NodeIterator, __construct, NULL, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
510 	/* Iterator implementations */
511 	PHP_ME(MeCab_NodeIterator,  current,    NULL, ZEND_ACC_PUBLIC)
512 	PHP_ME(MeCab_NodeIterator,  key,        NULL, ZEND_ACC_PUBLIC)
513 	PHP_ME(MeCab_NodeIterator,  next,       NULL, ZEND_ACC_PUBLIC)
514 	PHP_ME(MeCab_NodeIterator,  rewind,     NULL, ZEND_ACC_PUBLIC)
515 	PHP_ME(MeCab_NodeIterator,  valid,      NULL, ZEND_ACC_PUBLIC)
516 	PHP_FE_END
517 };
518 /* }}} */
519 
520 /* {{{ MeCab_Path methods[] */
521 #define PM_PATH_ME_MAPPING(methname, funcname) \
522 	PHP_ME_MAPPING(methname, mecab_path_ ## funcname, NULL, ZEND_ACC_PUBLIC)
523 
524 static zend_function_entry mecab_path_methods[] = {
525 	/* Constructor */
526 	PHP_ME(MeCab_Path, __construct, NULL, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
527 	/* Overloading implementations */
528 	PHP_ME(MeCab_Path, __get,   arginfo_mecab__magic_getter, ZEND_ACC_PUBLIC)
529 	PHP_ME(MeCab_Path, __isset, arginfo_mecab__magic_getter, ZEND_ACC_PUBLIC)
530 	/* Getters */
531 	PM_PATH_ME_MAPPING(getRNext, rnext)
532 	PM_PATH_ME_MAPPING(getLNext, lnext)
533 	PM_PATH_ME_MAPPING(getRNode, rnode)
534 	PM_PATH_ME_MAPPING(getLNode, lnode)
535 	PM_PATH_ME_MAPPING(getProb, prob)
536 	PM_PATH_ME_MAPPING(getCost, cost)
537 	PHP_FE_END
538 };
539 
540 static zend_function_entry mecab_path_deprecated_methods[] = {
541 	PHP_ME(MeCab_Path, __construct, NULL, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR | ZEND_ACC_DEPRECATED)
542 	PHP_FE_END
543 };
544 /* }}} methods */
545 
546 /* }}} class definitions */
547 
548 /* {{{ mecab_functions[] */
549 #define PM_NODE_FE(name) PHP_FE(mecab_node_ ## name, arginfo_mecab_node__node)
550 #define PM_NODELIST_FE(name) PHP_FE(mecab_node_ ## name, arginfo_mecab_node__list)
551 #define PM_PATH_FE(name) PHP_FE(mecab_path_ ## name, arginfo_mecab_path__path)
552 
553 static zend_function_entry mecab_functions[] = {
554 	ZEND_NS_NAMED_FE("MeCab", version, ZEND_FN(mecab_version), NULL)
555 	ZEND_NS_NAMED_FE("MeCab", split,   ZEND_FN(mecab_split),   arginfo_mecab_split)
556 	/* Get MeCab library version */
557 	PHP_FE(mecab_version, NULL)
558 	/* Wakati-Gaki function */
559 	PHP_FE(mecab_split, arginfo_mecab_split)
560 	/* MeCab API wrappers */
561 	PHP_FE(mecab_new,                   arginfo_mecab_new)
562 	PHP_FE(mecab_destroy,               arginfo_mecab__mecab)
563 	PHP_FE(mecab_get_partial,           arginfo_mecab__mecab)
564 	PHP_FE(mecab_set_partial,           arginfo_mecab_set_partial)
565 	PHP_FE(mecab_get_theta,             arginfo_mecab__mecab)
566 	PHP_FE(mecab_set_theta,             arginfo_mecab_set_theta)
567 	PHP_FE(mecab_get_lattice_level,     arginfo_mecab__mecab)
568 	PHP_FE(mecab_set_lattice_level,     arginfo_mecab_set_lattice_level)
569 	PHP_FE(mecab_get_all_morphs,        arginfo_mecab__mecab)
570 	PHP_FE(mecab_set_all_morphs,        arginfo_mecab_set_all_morphs)
571 	PHP_FE(mecab_sparse_tostr,          arginfo_mecab_sparse_tostr)
572 	PHP_FE(mecab_sparse_tonode,         arginfo_mecab_sparse_tonode)
573 	PHP_FE(mecab_nbest_sparse_tostr,    arginfo_mecab_nbest_sparse_tostr)
574 	PHP_FE(mecab_nbest_init,            arginfo_mecab_nbest_init)
575 	PHP_FE(mecab_nbest_next_tostr,      arginfo_mecab_nbest_next_tostr)
576 	PHP_FE(mecab_nbest_next_tonode,     arginfo_mecab__mecab)
577 	PHP_FE(mecab_format_node,           arginfo_mecab_format_node)
578 	PHP_FE(mecab_dictionary_info,       arginfo_mecab__mecab)
579 	/* Dumper for mecab_node */
580 	PHP_FE(mecab_node_toarray,          arginfo_mecab_node_toarray)
581 	PHP_FE(mecab_node_tostring,         arginfo_mecab_node__node)
582 	/* Getters for mecab_node */
583 	PM_NODE_FE(prev)
584 	PM_NODE_FE(next)
585 	PM_NODE_FE(enext)
586 	PM_NODE_FE(bnext)
587 	PM_NODE_FE(rpath)
588 	PM_NODE_FE(lpath)
589 	PM_NODE_FE(surface)
590 	PM_NODE_FE(feature)
591 	PM_NODE_FE(id)
592 	PM_NODE_FE(length)
593 	PM_NODE_FE(rlength)
594 	PM_NODE_FE(rcattr)
595 	PM_NODE_FE(lcattr)
596 	PM_NODE_FE(posid)
597 	PM_NODE_FE(char_type)
598 	PM_NODE_FE(stat)
599 	PM_NODE_FE(isbest)
600 	PM_NODE_FE(alpha)
601 	PM_NODE_FE(beta)
602 	PM_NODE_FE(prob)
603 	PM_NODE_FE(wcost)
604 	PM_NODE_FE(cost)
605 	/* Getters for mecab_path */
606 	PM_PATH_FE(rnext)
607 	PM_PATH_FE(lnext)
608 	PM_PATH_FE(rnode)
609 	PM_PATH_FE(lnode)
610 	PM_PATH_FE(prob)
611 	PM_PATH_FE(cost)
612 	PHP_FE_END
613 };
614 /* }}} */
615 
616 /* {{{ cross-extension dependencies */
617 
618 static zend_module_dep mecab_deps[] = {
619 	ZEND_MOD_REQUIRED("spl")
620 	{ NULL, NULL, NULL, 0 }
621 };
622 
623 /* }}} */
624 
625 /* {{{ mecab_module_entry */
626 zend_module_entry mecab_module_entry = {
627 	STANDARD_MODULE_HEADER_EX,
628 	NULL,
629 	mecab_deps,
630 	"mecab",
631 	mecab_functions,
632 	PHP_MINIT(mecab),
633 	PHP_MSHUTDOWN(mecab),
634 	NULL,
635 	NULL,
636 	PHP_MINFO(mecab),
637 	PHP_MECAB_MODULE_VERSION,
638 	PHP_MODULE_GLOBALS(mecab),
639 	PHP_GINIT(mecab),
640 	NULL,
641 	NULL,
642 	STANDARD_MODULE_PROPERTIES_EX
643 };
644 /* }}} */
645 
646 #ifdef COMPILE_DL_MECAB
647 ZEND_GET_MODULE(mecab)
648 #endif
649 
650 /* {{{ ini entries */
651 
PHP_INI_BEGIN()652 PHP_INI_BEGIN()
653 	STD_PHP_INI_ENTRY("mecab.default_rcfile", "", PHP_INI_ALL,
654 		OnUpdateString, default_rcfile, zend_mecab_globals, mecab_globals)
655 	STD_PHP_INI_ENTRY("mecab.default_dicdir", "", PHP_INI_ALL,
656 		OnUpdateString, default_dicdir, zend_mecab_globals, mecab_globals)
657 	STD_PHP_INI_ENTRY("mecab.default_userdic", "", PHP_INI_ALL,
658 		OnUpdateString, default_userdic, zend_mecab_globals, mecab_globals)
659 PHP_INI_END()
660 
661 /* }}} */
662 
663 /* {{{ PHP_MINIT_FUNCTION */
664 static PHP_MINIT_FUNCTION(mecab)
665 {
666 	REGISTER_INI_ENTRIES();
667 
668 	REGISTER_NS_STRING_CONSTANT("MeCab", "VERSION", (char *)mecab_version(), CONST_PERSISTENT | CONST_CS);
669 	PHP_MECAB_REGISTER_NS_CONSTANT(NOR_NODE);
670 	PHP_MECAB_REGISTER_NS_CONSTANT(UNK_NODE);
671 	PHP_MECAB_REGISTER_NS_CONSTANT(BOS_NODE);
672 	PHP_MECAB_REGISTER_NS_CONSTANT(EOS_NODE);
673 	PHP_MECAB_REGISTER_NS_CONSTANT(SYS_DIC);
674 	PHP_MECAB_REGISTER_NS_CONSTANT(USR_DIC);
675 	PHP_MECAB_REGISTER_NS_CONSTANT(UNK_DIC);
676 
677 	REGISTER_STRING_CONSTANT("MECAB_VERSION", (char *)mecab_version(), CONST_PERSISTENT | CONST_CS);
678 	PHP_MECAB_REGISTER_CONSTANT(MECAB_NOR_NODE);
679 	PHP_MECAB_REGISTER_CONSTANT(MECAB_UNK_NODE);
680 	PHP_MECAB_REGISTER_CONSTANT(MECAB_BOS_NODE);
681 	PHP_MECAB_REGISTER_CONSTANT(MECAB_EOS_NODE);
682 	PHP_MECAB_REGISTER_CONSTANT(MECAB_SYS_DIC);
683 	PHP_MECAB_REGISTER_CONSTANT(MECAB_USR_DIC);
684 	PHP_MECAB_REGISTER_CONSTANT(MECAB_UNK_DIC);
685 
686 	le_mecab = zend_register_list_destructors_ex(
687 			php_mecab_free_resource, NULL, "mecab", module_number);
688 	le_mecab_node = zend_register_list_destructors_ex(
689 			php_mecab_node_free_resource, NULL, "mecab_node", module_number);
690 	le_mecab_path = zend_register_list_destructors_ex(
691 			php_mecab_path_free_resource, NULL, "mecab_path", module_number);
692 
693 	ext_ce_Iterator = php_mecab_get_class_entry("iterator" TSRMLS_CC);
694 	ext_ce_IteratorAggregate = php_mecab_get_class_entry("iteratoraggregate" TSRMLS_CC);
695 	ext_ce_BadMethodCallException = php_mecab_get_class_entry("badmethodcallexception" TSRMLS_CC);
696 	ext_ce_InvalidArgumentException = php_mecab_get_class_entry("invalidargumentexception" TSRMLS_CC);
697 	ext_ce_OutOfRangeException = php_mecab_get_class_entry("outofrangeexception" TSRMLS_CC);
698 	if (ext_ce_Iterator == NULL ||
699 		ext_ce_IteratorAggregate == NULL ||
700 		ext_ce_BadMethodCallException == NULL ||
701 		ext_ce_InvalidArgumentException == NULL ||
702 		ext_ce_OutOfRangeException == NULL)
703 	{
704 		return FAILURE;
705 	}
706 	{
707 		zend_class_entry ce1, ce1a, ce1d;
708 
709 		INIT_NS_CLASS_ENTRY(ce1, "MeCab", "Tagger", mecab_methods);
710 		ce_MeCab_Tagger = zend_register_internal_class(&ce1 TSRMLS_CC);
711 		if (!ce_MeCab_Tagger) {
712 			return FAILURE;
713 		}
714 		ce_MeCab_Tagger->create_object = php_mecab_object_new;
715 
716 		memcpy(&php_mecab_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
717 		php_mecab_object_handlers.clone_obj = NULL;
718 
719 		zend_declare_class_constant_string(ce_MeCab_Tagger, "VERSION", 7, (char *)mecab_version() TSRMLS_CC);
720 		zend_declare_class_constant_long(ce_MeCab_Tagger, "SYS_DIC", 7, MECAB_SYS_DIC TSRMLS_CC);
721 		zend_declare_class_constant_long(ce_MeCab_Tagger, "USR_DIC", 7, MECAB_USR_DIC TSRMLS_CC);
722 		zend_declare_class_constant_long(ce_MeCab_Tagger, "UNK_DIC", 7, MECAB_UNK_DIC TSRMLS_CC);
723 
724 		zend_declare_class_constant_string(ce_MeCab_Tagger, "VERSION", 7, (char *)mecab_version() TSRMLS_CC);
725 		zend_declare_class_constant_long(ce_MeCab_Tagger, "SYS_DIC", 7, MECAB_SYS_DIC TSRMLS_CC);
726 		zend_declare_class_constant_long(ce_MeCab_Tagger, "USR_DIC", 7, MECAB_USR_DIC TSRMLS_CC);
727 		zend_declare_class_constant_long(ce_MeCab_Tagger, "UNK_DIC", 7, MECAB_UNK_DIC TSRMLS_CC);
728 
729 		INIT_CLASS_ENTRY(ce1a, "MeCab", mecab_deprecated_methods);
730 		ce_MeCab_Deprecated = zend_register_internal_class_ex(&ce1a, ce_MeCab_Tagger, ZEND_NS_NAME("MeCab", "Tagger") TSRMLS_CC);
731 		if (!ce_MeCab_Deprecated) {
732 			return FAILURE;
733 		}
734 		ce_MeCab_Deprecated->create_object = php_mecab_object_new;
735 
736 		INIT_CLASS_ENTRY(ce1d, "MeCab_Tagger", mecab_deprecated_methods);
737 		ce_MeCab_Tagger_Deprecated = zend_register_internal_class_ex(&ce1d, ce_MeCab_Tagger, ZEND_NS_NAME("MeCab", "Tagger") TSRMLS_CC);
738 		if (!ce_MeCab_Tagger_Deprecated) {
739 			return FAILURE;
740 		}
741 		ce_MeCab_Tagger_Deprecated->create_object = php_mecab_object_new;
742 	}
743 	{
744 		zend_class_entry ce2, ce2d, ce2i;
745 
746 		INIT_NS_CLASS_ENTRY(ce2, "MeCab", "Node", mecab_node_methods);
747 		ce_MeCab_Node = zend_register_internal_class(&ce2 TSRMLS_CC);
748 		if (!ce_MeCab_Node) {
749 			return FAILURE;
750 		}
751 		ce_MeCab_Node->create_object = php_mecab_node_object_new;
752 
753 		INIT_NS_CLASS_ENTRY(ce2i, "MeCab", "NodeIterator", mecab_iterator_methods);
754 		ce_MeCab_NodeIterator = zend_register_internal_class(&ce2i TSRMLS_CC);
755 		if (!ce_MeCab_NodeIterator) {
756 			return FAILURE;
757 		}
758 		ce_MeCab_NodeIterator->create_object = php_mecab_node_object_new;
759 
760 		memcpy(&php_mecab_node_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
761 		php_mecab_node_object_handlers.clone_obj = NULL;
762 
763 		zend_class_implements(ce_MeCab_Node TSRMLS_CC, 1, ext_ce_IteratorAggregate);
764 		zend_class_implements(ce_MeCab_NodeIterator TSRMLS_CC, 1, ext_ce_Iterator);
765 
766 		zend_declare_class_constant_long(ce_MeCab_Node, "NOR", 3, MECAB_NOR_NODE TSRMLS_CC);
767 		zend_declare_class_constant_long(ce_MeCab_Node, "UNK", 3, MECAB_UNK_NODE TSRMLS_CC);
768 		zend_declare_class_constant_long(ce_MeCab_Node, "BOS", 3, MECAB_BOS_NODE TSRMLS_CC);
769 		zend_declare_class_constant_long(ce_MeCab_Node, "EOS", 3, MECAB_EOS_NODE TSRMLS_CC);
770 
771 		zend_declare_class_constant_long(ce_MeCab_Node, "TRAVERSE_NEXT", 13, (long)TRAVERSE_NEXT TSRMLS_CC);
772 		zend_declare_class_constant_long(ce_MeCab_Node, "TRAVERSE_ENEXT", 14, (long)TRAVERSE_ENEXT TSRMLS_CC);
773 		zend_declare_class_constant_long(ce_MeCab_Node, "TRAVERSE_BNEXT", 14, (long)TRAVERSE_BNEXT TSRMLS_CC);
774 
775 		INIT_CLASS_ENTRY(ce2d, "MeCab_Node", mecab_node_deprecated_methods);
776 		ce_MeCab_Node_Deprecated = zend_register_internal_class_ex(&ce2d, ce_MeCab_Node, ZEND_NS_NAME("MeCab", "Node") TSRMLS_CC);
777 		if (!ce_MeCab_Node_Deprecated) {
778 			return FAILURE;
779 		}
780 		ce_MeCab_Node_Deprecated->create_object = php_mecab_node_object_new;
781 	}
782 	{
783 		zend_class_entry ce3, ce3d;
784 
785 		INIT_NS_CLASS_ENTRY(ce3, "MeCab", "Path", mecab_path_methods);
786 		ce_MeCab_Path = zend_register_internal_class(&ce3 TSRMLS_CC);
787 		if (!ce_MeCab_Path) {
788 			return FAILURE;
789 		}
790 		ce_MeCab_Path->create_object = php_mecab_path_object_new;
791 
792 		memcpy(&php_mecab_path_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
793 		php_mecab_path_object_handlers.clone_obj = NULL;
794 
795 		INIT_CLASS_ENTRY(ce3d, "MeCab_Path", mecab_path_deprecated_methods);
796 		ce_MeCab_Path_Deprecated = zend_register_internal_class_ex(&ce3d, ce_MeCab_Path, ZEND_NS_NAME("MeCab", "Path") TSRMLS_CC);
797 		if (!ce_MeCab_Path_Deprecated) {
798 			return FAILURE;
799 		}
800 		ce_MeCab_Path_Deprecated->create_object = php_mecab_path_object_new;
801 	}
802 
803 	return SUCCESS;
804 }
805 /* }}} */
806 
807 /* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(mecab)808 static PHP_MSHUTDOWN_FUNCTION(mecab)
809 {
810 	UNREGISTER_INI_ENTRIES();
811 	return SUCCESS;
812 }
813 /* }}} */
814 
815 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(mecab)816 static PHP_MINFO_FUNCTION(mecab)
817 {
818 	php_info_print_table_start();
819 	php_info_print_table_row(2, "MeCab Support", "enabled");
820 	php_info_print_table_row(2, "Module Version", PHP_MECAB_MODULE_VERSION);
821 	php_info_print_table_end();
822 
823 	php_info_print_table_start();
824 	php_info_print_table_header(3, "Version Info", "Compiled", "Linked");
825 	php_info_print_table_row(3, "MeCab Library", PHP_MECAB_VERSION_STRING, mecab_version());
826 	php_info_print_table_end();
827 
828 	DISPLAY_INI_ENTRIES();
829 }
830 /* }}} */
831 
832 /* {{{ PHP_GINIT_FUNCTION */
PHP_GINIT_FUNCTION(mecab)833 static PHP_GINIT_FUNCTION(mecab)
834 {
835 	mecab_globals->default_rcfile = NULL;
836 	mecab_globals->default_dicdir = NULL;
837 	mecab_globals->default_userdic = NULL;
838 }
839 /* }}} */
840 
841 /* {{{ internal function implementation for mecab_t */
842 
843 /* {{{ php_mecab_ctor()
844  * allocate for mecab
845  */
846 static php_mecab *
php_mecab_ctor(TSRMLS_D)847 php_mecab_ctor(TSRMLS_D)
848 {
849 	php_mecab *mecab = NULL;
850 
851 	mecab = (php_mecab *)ecalloc(1, sizeof(php_mecab));
852 	if (mecab == NULL) {
853 		return NULL;
854 	}
855 
856 	mecab->ptr = NULL;
857 	mecab->str = NULL;
858 	mecab->len = 0;
859 	mecab->ref = 1;
860 
861 	return mecab;
862 }
863 /* }}} */
864 
865 /* {{{ php_mecab_dtor()
866  * free the mecab
867  */
868 static void
php_mecab_dtor(php_mecab * mecab TSRMLS_DC)869 php_mecab_dtor(php_mecab *mecab TSRMLS_DC)
870 {
871 	mecab->ref--;
872 	if (mecab->ref == 0) {
873 		if (mecab->str != NULL) {
874 			efree(mecab->str);
875 		}
876 		mecab_destroy(mecab->ptr);
877 		efree(mecab);
878 	}
879 }
880 /* }}} */
881 
882 /* {{{ php_mecab_free_resource()
883  * free the mecab resource
884  */
885 static void
php_mecab_free_resource(zend_rsrc_list_entry * rsrc TSRMLS_DC)886 php_mecab_free_resource(zend_rsrc_list_entry *rsrc TSRMLS_DC)
887 {
888 	php_mecab_dtor((php_mecab *)rsrc->ptr TSRMLS_CC);
889 }
890 /* }}} */
891 
892 /* {{{ php_mecab_set_string()
893  * set string to the mecab
894  */
895 static void
php_mecab_set_string(php_mecab * mecab,const char * str,int len TSRMLS_DC)896 php_mecab_set_string(php_mecab *mecab, const char *str, int len TSRMLS_DC)
897 {
898 	if (mecab->str != NULL) {
899 		efree(mecab->str);
900 	}
901 	if (str == NULL) {
902 		mecab->str = NULL;
903 		mecab->len = 0;
904 	} else {
905 		mecab->str = estrndup(str, len);
906 		mecab->len = (size_t)len;
907 	}
908 }
909 /* }}} */
910 
911 /* {{{ php_mecab_object_new()
912  * allocate for mecab object
913  */
914 zend_object_value
php_mecab_object_new(zend_class_entry * ce TSRMLS_DC)915 php_mecab_object_new(zend_class_entry *ce TSRMLS_DC)
916 {
917 	zend_object_value retval;
918 	php_mecab_object *intern;
919 
920 	intern = (php_mecab_object *)ecalloc(1, sizeof(php_mecab_object));
921 	intern->ptr = php_mecab_ctor(TSRMLS_C);
922 
923 	zend_object_std_init(&intern->std, ce TSRMLS_CC);
924 	object_properties_init(&intern->std, ce);
925 
926 	retval.handle = zend_objects_store_put(intern,
927 			(zend_objects_store_dtor_t)zend_objects_destroy_object,
928 			(zend_objects_free_object_storage_t)php_mecab_free_object_storage,
929 			NULL TSRMLS_CC);
930 	retval.handlers = &php_mecab_object_handlers;
931 
932 	return retval;
933 }
934 /* }}} */
935 
936 /* {{{ php_mecab_free_object_storage()
937  * free the mecab object
938  */
939 static void
php_mecab_free_object_storage(void * object TSRMLS_DC)940 php_mecab_free_object_storage(void *object TSRMLS_DC)
941 {
942 	php_mecab_object *intern = (php_mecab_object *)object;
943 	php_mecab_dtor(intern->ptr TSRMLS_CC);
944 	zend_object_std_dtor(&intern->std TSRMLS_CC);
945 	efree(object);
946 }
947 /* }}} */
948 
949 /* }}} mecab_t */
950 
951 /* {{{ internal function implementation for mecab_node_t */
952 
953 /* {{{ php_mecab_node_ctor()
954  * allocate for mecab_node
955  */
956 static php_mecab_node *
php_mecab_node_ctor(TSRMLS_D)957 php_mecab_node_ctor(TSRMLS_D)
958 {
959 	php_mecab_node *node = NULL;
960 
961 	node = (php_mecab_node *)ecalloc(1, sizeof(php_mecab_node));
962 	if (node == NULL) {
963 		return NULL;
964 	}
965 
966 	node->tagger = NULL;
967 	node->ptr = NULL;
968 
969 	return node;
970 }
971 /* }}} */
972 
973 /* {{{ php_mecab_node_dtor()
974  * free the mecab_node
975  */
976 static void
php_mecab_node_dtor(php_mecab_node * node TSRMLS_DC)977 php_mecab_node_dtor(php_mecab_node *node TSRMLS_DC)
978 {
979 	if (node->tagger != NULL) {
980 		php_mecab_dtor(node->tagger TSRMLS_CC);
981 	}
982 	efree(node);
983 }
984 /* }}} */
985 
986 /* {{{ php_mecab_node_free_resource()
987  * free the mecab_node resource
988  */
989 static void
php_mecab_node_free_resource(zend_rsrc_list_entry * rsrc TSRMLS_DC)990 php_mecab_node_free_resource(zend_rsrc_list_entry *rsrc TSRMLS_DC)
991 {
992 	php_mecab_node_dtor((php_mecab_node *)rsrc->ptr TSRMLS_CC);
993 }
994 /* }}} */
995 
996 /* {{{ php_mecab_node_set_tagger()
997  * set mecab to the mecab_node
998  */
999 static void
php_mecab_node_set_tagger(php_mecab_node * node,php_mecab * mecab TSRMLS_DC)1000 php_mecab_node_set_tagger(php_mecab_node *node, php_mecab *mecab TSRMLS_DC)
1001 {
1002 	if (node->tagger != NULL) {
1003 		php_mecab_dtor(node->tagger TSRMLS_CC);
1004 	}
1005 	if (mecab == NULL) {
1006 		node->tagger = NULL;
1007 	} else {
1008 		node->tagger = mecab;
1009 		node->tagger->ref++;
1010 	}
1011 }
1012 /* }}} */
1013 
1014 /* {{{ php_mecab_node_object_new()
1015  * allocate for mecab_node object
1016  */
1017 zend_object_value
php_mecab_node_object_new(zend_class_entry * ce TSRMLS_DC)1018 php_mecab_node_object_new(zend_class_entry *ce TSRMLS_DC)
1019 {
1020 	zend_object_value retval;
1021 	php_mecab_node_object *intern;
1022 
1023 	intern = (php_mecab_node_object *)ecalloc(1, sizeof(php_mecab_node_object));
1024 	intern->ptr = php_mecab_node_ctor(TSRMLS_C);
1025 	intern->mode = TRAVERSE_NEXT;
1026 
1027 	zend_object_std_init(&intern->std, ce TSRMLS_CC);
1028 	object_properties_init(&intern->std, ce);
1029 
1030 	retval.handle = zend_objects_store_put(intern,
1031 			(zend_objects_store_dtor_t)zend_objects_destroy_object,
1032 			(zend_objects_free_object_storage_t)php_mecab_node_free_object_storage,
1033 			NULL TSRMLS_CC);
1034 	retval.handlers = &php_mecab_node_object_handlers;
1035 
1036 	return retval;
1037 }
1038 /* }}} */
1039 
1040 /* {{{ php_mecab_node_free_object_storage()
1041  * free the mecab_node object
1042  */
1043 static void
php_mecab_node_free_object_storage(void * object TSRMLS_DC)1044 php_mecab_node_free_object_storage(void *object TSRMLS_DC)
1045 {
1046 	php_mecab_node_object *intern = (php_mecab_node_object *)object;
1047 	php_mecab_node_dtor(intern->ptr TSRMLS_CC);
1048 	zend_object_std_dtor(&intern->std TSRMLS_CC);
1049 	efree(object);
1050 }
1051 /* }}} */
1052 
1053 /* }}} mecab_node_t */
1054 
1055 /* {{{ php_mecab_path_ctor()
1056  * allocate for mecab_path
1057  */
1058 static php_mecab_path *
php_mecab_path_ctor(TSRMLS_D)1059 php_mecab_path_ctor(TSRMLS_D)
1060 {
1061 	php_mecab_path *path = NULL;
1062 
1063 	path = (php_mecab_path *)ecalloc(1, sizeof(php_mecab_path));
1064 	if (path == NULL) {
1065 		return NULL;
1066 	}
1067 
1068 	path->tagger = NULL;
1069 	path->ptr = NULL;
1070 
1071 	return path;
1072 }
1073 /* }}} */
1074 
1075 /* {{{ php_mecab_path_dtor()
1076  * free the mecab_path
1077  */
1078 static void
php_mecab_path_dtor(php_mecab_path * path TSRMLS_DC)1079 php_mecab_path_dtor(php_mecab_path *path TSRMLS_DC)
1080 {
1081 	if (path->tagger != NULL) {
1082 		php_mecab_dtor(path->tagger TSRMLS_CC);
1083 	}
1084 	efree(path);
1085 }
1086 /* }}} */
1087 
1088 /* {{{ php_mecab_path_free_resource()
1089  * free the mecab_path resource
1090  */
1091 static void
php_mecab_path_free_resource(zend_rsrc_list_entry * rsrc TSRMLS_DC)1092 php_mecab_path_free_resource(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1093 {
1094 	php_mecab_path_dtor((php_mecab_path *)rsrc->ptr TSRMLS_CC);
1095 }
1096 /* }}} */
1097 
1098 /* {{{ php_mecab_path_set_tagger()
1099  * set mecab_node to the mecab_path
1100  */
1101 static void
php_mecab_path_set_tagger(php_mecab_path * path,php_mecab * mecab TSRMLS_DC)1102 php_mecab_path_set_tagger(php_mecab_path *path, php_mecab *mecab TSRMLS_DC)
1103 {
1104 	if (path->tagger != NULL) {
1105 		php_mecab_dtor(path->tagger TSRMLS_CC);
1106 	}
1107 	if (mecab == NULL) {
1108 		path->tagger = NULL;
1109 	} else {
1110 		path->tagger = mecab;
1111 		path->tagger->ref++;
1112 	}
1113 }
1114 /* }}} */
1115 
1116 /* {{{ php_mecab_path_object_new()
1117  * allocate for mecab_path object
1118  */
1119 zend_object_value
php_mecab_path_object_new(zend_class_entry * ce TSRMLS_DC)1120 php_mecab_path_object_new(zend_class_entry *ce TSRMLS_DC)
1121 {
1122 	zend_object_value retval;
1123 	php_mecab_path_object *intern;
1124 
1125 	intern = (php_mecab_path_object *)ecalloc(1, sizeof(php_mecab_path_object));
1126 	intern->ptr = php_mecab_path_ctor(TSRMLS_C);
1127 
1128 	zend_object_std_init(&intern->std, ce TSRMLS_CC);
1129 	object_properties_init(&intern->std, ce);
1130 
1131 	retval.handle = zend_objects_store_put(intern,
1132 			(zend_objects_store_dtor_t)zend_objects_destroy_object,
1133 			(zend_objects_free_object_storage_t)php_mecab_path_free_object_storage,
1134 			NULL TSRMLS_CC);
1135 	retval.handlers = &php_mecab_path_object_handlers;
1136 
1137 	return retval;
1138 }
1139 /* }}} */
1140 
1141 /* {{{ php_mecab_path_free_object_storage()
1142  * free the mecab_path object
1143  */
1144 static void
php_mecab_path_free_object_storage(void * object TSRMLS_DC)1145 php_mecab_path_free_object_storage(void *object TSRMLS_DC)
1146 {
1147 	php_mecab_path_object *intern = (php_mecab_path_object *)object;
1148 	php_mecab_path_dtor(intern->ptr TSRMLS_CC);
1149 	zend_object_std_dtor(&intern->std TSRMLS_CC);
1150 	efree(object);
1151 }
1152 /* }}} */
1153 
1154 /* }}} mecab_path_t */
1155 
1156 /* {{{ php_mecab_node_get_sibling()
1157  * get sibling node from mecab_node
1158  */
1159 static zval *
php_mecab_node_get_sibling(zval * zv,zval * object,php_mecab_node * xnode,php_mecab_node_rel rel TSRMLS_DC)1160 php_mecab_node_get_sibling(zval *zv, zval *object, php_mecab_node *xnode, php_mecab_node_rel rel TSRMLS_DC)
1161 {
1162 	const mecab_node_t *node = xnode->ptr;
1163 	php_mecab_node *xsbl = NULL;
1164 	const mecab_node_t *sbl = NULL;
1165 	zval *retval = NULL;
1166 
1167 	if (zv == NULL) {
1168 		MAKE_STD_ZVAL(retval);
1169 	} else {
1170 		zval_dtor(zv);
1171 		retval = zv;
1172 	}
1173 
1174 	/* scan */
1175 	if (rel == NODE_PREV) {
1176 		sbl = node->prev;
1177 	} else if (rel == NODE_NEXT) {
1178 		sbl = node->next;
1179 	} else if (rel == NODE_ENEXT) {
1180 		sbl = node->enext;
1181 	} else if (rel == NODE_BNEXT) {
1182 		sbl = node->bnext;
1183 	} else {
1184 		ZVAL_FALSE(retval);
1185 		return retval;
1186 	}
1187 
1188 	if (sbl == NULL) {
1189 		ZVAL_NULL(retval);
1190 		return retval;
1191 	}
1192 
1193 	/* set return value */
1194 	if (object) {
1195 		php_mecab_node_object *newobj;
1196 		object_init_ex(retval, ce_MeCab_Node);
1197 		PHP_MECAB_FETCH_OBJECT(newobj, php_mecab_node_object *, retval);
1198 		xsbl = newobj->ptr;
1199 	} else {
1200 		xsbl = php_mecab_node_ctor(TSRMLS_C);
1201 		ZEND_REGISTER_RESOURCE(retval, xsbl, le_mecab_node);
1202 	}
1203 	xsbl->ptr = sbl;
1204 	php_mecab_node_set_tagger(xsbl, xnode->tagger TSRMLS_CC);
1205 
1206 	return retval;
1207 }
1208 /* }}} */
1209 
1210 /* {{{ php_mecab_node_get_path()
1211  * get related path from mecab_node
1212  */
1213 static zval *
php_mecab_node_get_path(zval * zv,zval * object,php_mecab_node * xnode,php_mecab_node_rel rel TSRMLS_DC)1214 php_mecab_node_get_path(zval *zv, zval *object, php_mecab_node *xnode, php_mecab_node_rel rel TSRMLS_DC)
1215 {
1216 	const mecab_node_t *node = xnode->ptr;
1217 	php_mecab_path *xpath = NULL;
1218 	const mecab_path_t *path = NULL;
1219 	zval *retval = NULL;
1220 
1221 	if (zv == NULL) {
1222 		MAKE_STD_ZVAL(retval);
1223 	} else {
1224 		zval_dtor(zv);
1225 		retval = zv;
1226 	}
1227 
1228 	/* scan */
1229 	if (rel == NODE_RPATH) {
1230 		path = node->rpath;
1231 	} else if (rel == NODE_LPATH) {
1232 		path = node->lpath;
1233 	} else {
1234 		ZVAL_FALSE(retval);
1235 		return retval;
1236 	}
1237 
1238 	if (path == NULL) {
1239 		ZVAL_NULL(retval);
1240 		return retval;
1241 	}
1242 
1243 	/* set return value */
1244 	if (object) {
1245 		php_mecab_path_object *newobj;
1246 		object_init_ex(retval, ce_MeCab_Path);
1247 		PHP_MECAB_FETCH_OBJECT(newobj, php_mecab_path_object *, retval);
1248 		xpath = newobj->ptr;
1249 	} else {
1250 		xpath = php_mecab_path_ctor(TSRMLS_C);
1251 		ZEND_REGISTER_RESOURCE(retval, xpath, le_mecab_path);
1252 	}
1253 	xpath->ptr = path;
1254 	php_mecab_path_set_tagger(xpath, xnode->tagger TSRMLS_CC);
1255 
1256 	return retval;
1257 }
1258 /* }}} */
1259 
1260 /* {{{ php_mecab_path_get_sibling()
1261  * get sibling path from mecab_path
1262  */
1263 static zval *
php_mecab_path_get_sibling(zval * zv,zval * object,php_mecab_path * xpath,php_mecab_path_rel rel TSRMLS_DC)1264 php_mecab_path_get_sibling(zval *zv, zval *object, php_mecab_path *xpath, php_mecab_path_rel rel TSRMLS_DC)
1265 {
1266 	const mecab_path_t *path = xpath->ptr;
1267 	php_mecab_path *xsbl = NULL;
1268 	const mecab_path_t *sbl = NULL;
1269 	zval *retval = NULL;
1270 
1271 	if (zv == NULL) {
1272 		MAKE_STD_ZVAL(retval);
1273 	} else {
1274 		zval_dtor(zv);
1275 		retval = zv;
1276 	}
1277 
1278 	/* scan */
1279 	if (rel == PATH_RNEXT) {
1280 		sbl = path->rnext;
1281 	} else if (rel == PATH_LNEXT) {
1282 		sbl = path->lnext;
1283 	} else {
1284 		ZVAL_FALSE(retval);
1285 		return retval;
1286 	}
1287 
1288 	if (sbl == NULL) {
1289 		ZVAL_NULL(retval);
1290 		return retval;
1291 	}
1292 
1293 	/* set return value */
1294 	if (object) {
1295 		php_mecab_path_object *newobj;
1296 		object_init_ex(retval, ce_MeCab_Path);
1297 		PHP_MECAB_FETCH_OBJECT(newobj, php_mecab_path_object *, retval);
1298 		xsbl = newobj->ptr;
1299 	} else {
1300 		xsbl = php_mecab_path_ctor(TSRMLS_C);
1301 		ZEND_REGISTER_RESOURCE(retval, xsbl, le_mecab_path);
1302 	}
1303 	xsbl->ptr = sbl;
1304 	php_mecab_path_set_tagger(xsbl, xpath->tagger TSRMLS_CC);
1305 
1306 	return retval;
1307 }
1308 /* }}} */
1309 
1310 /* {{{ php_mecab_path_get_node()
1311  * get related node from mecab_path
1312  */
1313 static zval *
php_mecab_path_get_node(zval * zv,zval * object,php_mecab_path * xpath,php_mecab_path_rel rel TSRMLS_DC)1314 php_mecab_path_get_node(zval *zv, zval *object, php_mecab_path *xpath, php_mecab_path_rel rel TSRMLS_DC)
1315 {
1316 	const mecab_path_t *path = xpath->ptr;
1317 	php_mecab_node *xnode = NULL;
1318 	const mecab_node_t *node = NULL;
1319 	zval *retval = NULL;
1320 
1321 	if (zv == NULL) {
1322 		MAKE_STD_ZVAL(retval);
1323 	} else {
1324 		zval_dtor(zv);
1325 		retval = zv;
1326 	}
1327 
1328 	/* scan */
1329 	if (rel == PATH_RNODE) {
1330 		node = path->rnode;
1331 	} else if (rel == PATH_LNODE) {
1332 		node = path->lnode;
1333 	} else {
1334 		ZVAL_FALSE(retval);
1335 		return retval;
1336 	}
1337 
1338 	if (node == NULL) {
1339 		ZVAL_NULL(retval);
1340 		return retval;
1341 	}
1342 
1343 	/* set return value */
1344 	if (object) {
1345 		php_mecab_node_object *newobj;
1346 		object_init_ex(retval, ce_MeCab_Node);
1347 		PHP_MECAB_FETCH_OBJECT(newobj, php_mecab_node_object *, retval);
1348 		xnode = newobj->ptr;
1349 	} else {
1350 		xnode = php_mecab_node_ctor(TSRMLS_C);
1351 		ZEND_REGISTER_RESOURCE(retval, xnode, le_mecab_node);
1352 	}
1353 	xnode->ptr = node;
1354 	php_mecab_node_set_tagger(xnode, xpath->tagger TSRMLS_CC);
1355 
1356 	return retval;
1357 }
1358 /* }}} */
1359 
1360 /* {{{ php_mecab_node_get_sibling_wrapper()
1361  * wraps php_mecab_node_get_sibling()
1362  */
1363 static void
php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAMETERS,php_mecab_node_rel rel)1364 php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_node_rel rel)
1365 {
1366 	/* declaration of the resources */
1367 	zval *object = getThis();
1368 	zval *znode = NULL;
1369 	php_mecab_node *xnode = NULL;
1370 
1371 	/* parse the arguments */
1372 	PHP_MECAB_NODE_INTERNAL_FROM_PARAMETER();
1373 
1374 	php_mecab_node_get_sibling(return_value, object, xnode, rel TSRMLS_CC);
1375 }
1376 /* }}} */
1377 
1378 /* {{{ php_mecab_node_get_path_wrapper()
1379  * wraps php_mecab_node_get_path()
1380  */
1381 static void
php_mecab_node_get_path_wrapper(INTERNAL_FUNCTION_PARAMETERS,php_mecab_node_rel rel)1382 php_mecab_node_get_path_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_node_rel rel)
1383 {
1384 	/* declaration of the resources */
1385 	zval *object = getThis();
1386 	zval *znode = NULL;
1387 	php_mecab_node *xnode = NULL;
1388 
1389 	/* parse the arguments */
1390 	PHP_MECAB_NODE_INTERNAL_FROM_PARAMETER();
1391 
1392 	php_mecab_node_get_path(return_value, object, xnode, rel TSRMLS_CC);
1393 }
1394 /* }}} */
1395 
1396 /* {{{ php_mecab_path_get_sibling_wrapper()
1397  * wraps php_mecab_path_get_sibling()
1398  */
1399 static void
php_mecab_path_get_sibling_wrapper(INTERNAL_FUNCTION_PARAMETERS,php_mecab_path_rel rel)1400 php_mecab_path_get_sibling_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_path_rel rel)
1401 {
1402 	/* declaration of the resources */
1403 	zval *object = getThis();
1404 	zval *zpath = NULL;
1405 	php_mecab_path *xpath = NULL;
1406 
1407 	/* parse the arguments */
1408 	PHP_MECAB_PATH_INTERNAL_FROM_PARAMETER();
1409 
1410 	php_mecab_path_get_sibling(return_value, object, xpath, rel TSRMLS_CC);
1411 }
1412 /* }}} */
1413 
1414 /* {{{ php_mecab_path_get_node_wrapper()
1415  * wraps php_mecab_path_get_path()
1416  */
1417 static void
php_mecab_path_get_node_wrapper(INTERNAL_FUNCTION_PARAMETERS,php_mecab_path_rel rel)1418 php_mecab_path_get_node_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_path_rel rel)
1419 {
1420 	/* declaration of the resources */
1421 	zval *object = getThis();
1422 	zval *zpath = NULL;
1423 	php_mecab_path *xpath = NULL;
1424 
1425 	/* parse the arguments */
1426 	PHP_MECAB_PATH_INTERNAL_FROM_PARAMETER();
1427 
1428 	php_mecab_path_get_node(return_value, object, xpath, rel TSRMLS_CC);
1429 }
1430 /* }}} */
1431 
1432 /* {{{ php_mecab_get_class_entry()
1433  * get the class entry
1434  */
1435 static zend_class_entry *
php_mecab_get_class_entry(const char * lcname TSRMLS_DC)1436 php_mecab_get_class_entry(const char *lcname TSRMLS_DC)
1437 {
1438 	zend_class_entry **pce;
1439 	if (zend_hash_find(CG(class_table), lcname, strlen(lcname) + 1, (void **)&pce) == SUCCESS) {
1440 		return *pce;
1441 	} else {
1442 		return NULL;
1443 	}
1444 }
1445 /* }}} */
1446 
1447 /* {{{ php_mecab_node_list_method()
1448  * check file/dicectory accessibility
1449  */
1450 static zend_bool
php_mecab_check_path(const char * path,size_t length,char * real_path TSRMLS_DC)1451 php_mecab_check_path(const char *path, size_t length, char *real_path TSRMLS_DC)
1452 {
1453 	char *full_path;
1454 
1455 	if (strlen(path) != length ||
1456 		(full_path = expand_filepath(path, real_path TSRMLS_CC)) == NULL)
1457 	{
1458 		return 0;
1459 	}
1460 
1461 	if (VCWD_ACCESS(full_path, F_OK) != 0 ||
1462 		VCWD_ACCESS(full_path, R_OK) != 0 ||
1463 		php_check_open_basedir(full_path TSRMLS_CC))
1464 	{
1465 		if (real_path == NULL) {
1466 			efree(full_path);
1467 		}
1468 		return 0;
1469 	}
1470 
1471 #if !defined(PHP_VERSION_ID) || PHP_VERSION_ID < 50400
1472 	if (PG(safe_mode) && !php_checkuid(full_path, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
1473 		if (real_path == NULL) {
1474 			efree(full_path);
1475 		}
1476 		return 0;
1477 	}
1478 #endif
1479 
1480 	if (real_path == NULL) {
1481 		efree(full_path);
1482 	}
1483 	return 1;
1484 }
1485 /* }}} */
1486 
1487 /* {{{ macro for checking constructor options */
1488 
1489 /* check if default parameter is set */
1490 #define PHP_MECAB_CHECK_DEFAULT(name) \
1491 	(MECAB_G(default_##name) != NULL && MECAB_G(default_##name)[0] != '\0')
1492 
1493 #define PHP_MECAB_GETOPT_FAILURE -1
1494 #define PHP_MECAB_GETOPT_SUCCESS 0
1495 #define PHP_MECAB_GETOPT_FLAG_EXPECTED    (1 << 0)
1496 #define PHP_MECAB_GETOPT_RCFILE_EXPECTED  (1 << 2)
1497 #define PHP_MECAB_GETOPT_DICDIR_EXPECTED  (1 << 3)
1498 #define PHP_MECAB_GETOPT_USERDIC_EXPECTED (1 << 4)
1499 #define PHP_MECAB_GETOPT_PATH_EXPECTED \
1500 	(PHP_MECAB_GETOPT_RCFILE_EXPECTED | PHP_MECAB_GETOPT_DICDIR_EXPECTED | PHP_MECAB_GETOPT_USERDIC_EXPECTED)
1501 
1502 /* check for option */
1503 static int
php_mecab_check_option(const char * option)1504 php_mecab_check_option(const char *option)
1505 {
1506 	/* not an option */
1507 	if (*option != '-') {
1508 		return PHP_MECAB_GETOPT_FAILURE;
1509 	}
1510 
1511 	/* resource file */
1512 	if (!strcmp(option, "-r") || !strcmp(option, "--rcfile")) {
1513 		return PHP_MECAB_GETOPT_RCFILE_EXPECTED;
1514 	}
1515 
1516 	/* system dicdir */
1517 	if (!strcmp(option, "-d") || !strcmp(option, "--dicdir")) {
1518 		return PHP_MECAB_GETOPT_DICDIR_EXPECTED;
1519 	}
1520 
1521 	/* user dictionary */
1522 	if (!strcmp(option, "-u") || !strcmp(option, "--userdic")) {
1523 		return PHP_MECAB_GETOPT_USERDIC_EXPECTED;
1524 	}
1525 
1526 	/* options whose parameter is not filename */
1527 	if (!strcmp(option, "-l") || !strcmp(option, "--lattice-level") ||
1528 		!strcmp(option, "-O") || !strcmp(option, "--output-format-type") ||
1529 		!strcmp(option, "-F") || !strcmp(option, "--node-format") ||
1530 		!strcmp(option, "-U") || !strcmp(option, "--unk-format") ||
1531 		!strcmp(option, "-B") || !strcmp(option, "--bos-format") ||
1532 		!strcmp(option, "-E") || !strcmp(option, "--eos-format") ||
1533 		!strcmp(option, "-x") || !strcmp(option, "--unk-feature") ||
1534 		!strcmp(option, "-b") || !strcmp(option, "--input-buffer-size") ||
1535 		!strcmp(option, "-N") || !strcmp(option, "--nbest") ||
1536 		!strcmp(option, "-t") || !strcmp(option, "--theta"))
1537 	{
1538 		return PHP_MECAB_GETOPT_SUCCESS;
1539 	}
1540 
1541 	/* options which does not have parameter */
1542 	if (!strcmp(option, "-a") || !strcmp(option, "--all-morphs") ||
1543 		!strcmp(option, "-p") || !strcmp(option, "--partial") ||
1544 		!strcmp(option, "-C") || !strcmp(option, "--allocate-sentence"))
1545 	{
1546 		return (PHP_MECAB_GETOPT_SUCCESS | PHP_MECAB_GETOPT_FLAG_EXPECTED);
1547 	}
1548 
1549 	/* invalid options */
1550 	return PHP_MECAB_GETOPT_FAILURE;
1551 }
1552 
1553 /* check for open_basedir and safe_mode */
1554 #define PHP_MECAB_CHECK_FILE(path, length) \
1555 { \
1556 	if (!php_mecab_check_path((path), (length), resolved_path TSRMLS_CC)) { \
1557 		efree(argv); \
1558 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s' does not exist or is not readable", (path)); \
1559 		RETURN_FALSE; \
1560 	} \
1561 	flag_expected = 1; \
1562 	path_expected = 0; \
1563 }
1564 
1565 /* }}} */
1566 
1567 /* {{{ Functions */
1568 
1569 /* {{{ proto string mecab_version(void) */
1570 /**
1571  * string mecab_version(void)
1572  *
1573  * Get the version number of MeCab.
1574  *
1575  * @return	string	The version of linked MeCab library.
1576  */
PHP_FUNCTION(mecab_version)1577 static PHP_FUNCTION(mecab_version)
1578 {
1579 	if (ZEND_NUM_ARGS() != 0) {
1580 		WRONG_PARAM_COUNT;
1581 	}
1582 	RETURN_STRING((char *)mecab_version(), 1);
1583 }
1584 /* }}} mecab_version */
1585 
1586 /* {{{ proto array mecab_split(string str[, string dicdir[, string userdic]]) */
1587 /**
1588  * array mecab_split(string str[, string dicdir[, string userdic]])
1589  * array MeCab_Tagger::split(string str[, string dicdir[, string userdic]])
1590  *
1591  * Split string into an array of morphemes.
1592  *
1593  * @param	string	$str	The target string.
1594  * @param	string	$dicdir	The path for system dictionary.
1595  * @param	string	$userdic	The path for user dictionary.
1596  * @return	array
1597  */
PHP_FUNCTION(mecab_split)1598 static PHP_FUNCTION(mecab_split)
1599 {
1600 	/* variables from argument */
1601 	const char *str = NULL;
1602 	int str_len = 0;
1603 	const char *dicdir = NULL;
1604 	int dicdir_len = 0;
1605 	const char *userdic = NULL;
1606 	int userdic_len = 0;
1607 
1608 	/* local variables */
1609 	mecab_t *mecab = NULL;
1610 	const mecab_node_t *node = NULL;
1611 	int argc = 2;
1612 	char *argv[5] = { "mecab", "-Owakati", NULL, NULL, NULL };
1613 	char pathbuf[2][PATHBUFSIZE] = {{'\0'}};
1614 	char *dicdir_buf = &(pathbuf[0][0]);
1615 	char *userdic_buf = &(pathbuf[1][0]);
1616 
1617 	/* parse arguments */
1618 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!s!",
1619 			&str, &str_len, &dicdir, &dicdir_len, &userdic, &userdic_len) == FAILURE)
1620 	{
1621 		return;
1622 	}
1623 
1624 	/* apply default options */
1625 	if (dicdir_len == 0 && PHP_MECAB_CHECK_DEFAULT(dicdir)) {
1626 		dicdir = MECAB_G(default_dicdir);
1627 		dicdir_len = (int)strlen(MECAB_G(default_dicdir));
1628 	}
1629 	if (dicdir_len == 0 && PHP_MECAB_CHECK_DEFAULT(userdic)) {
1630 		userdic = MECAB_G(default_userdic);
1631 		userdic_len = (int)strlen(MECAB_G(default_userdic));
1632 	}
1633 
1634 	/* check for dictionary */
1635 	if (dicdir != NULL && dicdir_len > 0) {
1636 		char *dicdir_ptr = dicdir_buf;
1637 		*dicdir_ptr++ = '-';
1638 		*dicdir_ptr++ = 'd';
1639 		if (!php_mecab_check_path(dicdir, dicdir_len, dicdir_ptr TSRMLS_CC)) {
1640 			php_error_docref(NULL TSRMLS_CC, E_WARNING,
1641 					"'%s' does not exist or is not readable", dicdir);
1642 			RETURN_FALSE;
1643 		}
1644 		argv[argc++] = dicdir_buf;
1645 	}
1646 	if (userdic != NULL && userdic_len > 0) {
1647 		char *userdic_ptr = userdic_buf;
1648 		*userdic_ptr++ = '-';
1649 		*userdic_ptr++ = 'u';
1650 		if (!php_mecab_check_path(userdic, userdic_len, userdic_ptr TSRMLS_CC)) {
1651 			php_error_docref(NULL TSRMLS_CC, E_WARNING,
1652 					"'%s' does not exist or is not readable", userdic);
1653 			RETURN_FALSE;
1654 		}
1655 		argv[argc++] = userdic_buf;
1656 	}
1657 
1658 	/* create mecab object */
1659 	mecab = mecab_new(argc, argv);
1660 
1661 	/* on error */
1662 	if (mecab == NULL) {
1663 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(NULL));
1664 		RETURN_FALSE;
1665 	}
1666 
1667 	/* parse the string */
1668 	node = mecab_sparse_tonode(mecab, str);
1669 	if (node == NULL) {
1670 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
1671 		mecab_destroy(mecab);
1672 		RETURN_FALSE;
1673 	}
1674 
1675 	/* initialize */
1676 	array_init(return_value);
1677 
1678 	/* put surfaces of each node to return value */
1679 	while (node != NULL) {
1680 		if (node->length > 0) {
1681 			add_next_index_stringl(return_value, (char *)node->surface, (int)node->length, 1);
1682 		}
1683 		node = node->next;
1684 	}
1685 
1686 	/* free mecab object */
1687 	mecab_destroy(mecab);
1688 }
1689 /* }}} mecab_split */
1690 
1691 /* {{{ proto resource mecab mecab_new([array options]) */
1692 /**
1693  * resource mecab mecab_new([array options])
1694  * object MeCab_Tagger MeCab_Tagger::__construct([array options])
1695  *
1696  * Create new tagger resource of MeCab.
1697  *
1698  * @param	array	$options	The analysis/output options. (optional)
1699  *								The values are same to command line options.
1700  *								The detail is found in the web site and/or the manpage of MeCab.
1701  * @return	resource mecab	A tagger resource of MeCab.
1702  */
PHP_FUNCTION(mecab_new)1703 static PHP_FUNCTION(mecab_new)
1704 {
1705 	/* declaration of the resources */
1706 	zval *object = getThis();
1707 	php_mecab *xmecab = NULL;
1708 	mecab_t *mecab = NULL;
1709 
1710 	/* declaration of the arguments */
1711 	zval *zoptions = NULL;
1712 	HashTable *options = NULL;
1713 
1714 	/* declaration of the local variables */
1715 	size_t min_argc = 5; /* "mecab" + "-r" + "-d" + "-u" + NULL  */
1716 	int argc = 1;
1717 	char **argv = NULL;
1718 	int flag_expected = 1;
1719 	int path_expected = 0;
1720 	char pathbuf[3][PATHBUFSIZE] = {{'\0'}};
1721 	char *rcfile_buf = &(pathbuf[0][0]);
1722 	char *dicdir_buf = &(pathbuf[1][0]);
1723 	char *userdic_buf = &(pathbuf[2][0]);
1724 	char *resolved_path = NULL;
1725 
1726 	/* parse arguments */
1727 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &zoptions) == FAILURE) {
1728 		return;
1729 	}
1730 
1731 	/* parse options */
1732 	if (zoptions != NULL) {
1733 		int getopt_result = 0;
1734 		char *key;
1735 		uint len;
1736 		ulong idx;
1737 		zval **entry;
1738 
1739 		ALLOC_HASHTABLE(options);
1740 
1741 		zend_hash_init(options, zend_hash_num_elements(Z_ARRVAL_P(zoptions)), NULL, ZVAL_PTR_DTOR, 0);
1742 		zend_hash_copy(options, Z_ARRVAL_P(zoptions), (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval *));
1743 
1744 		argv = (char **)ecalloc(2 * zend_hash_num_elements(options) + min_argc, sizeof(char *));
1745 
1746 		while (zend_hash_get_current_data(options, (void **)&entry) == SUCCESS) {
1747 			convert_to_string_ex(entry);
1748 
1749 			switch (zend_hash_get_current_key_ex(options, &key, &len, &idx, 0, NULL)) {
1750 			  case HASH_KEY_IS_STRING:
1751 				getopt_result = php_mecab_check_option(key);
1752 				if (getopt_result == FAILURE) {
1753 					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option '%s' given", key);
1754 					efree(argv);
1755 					RETURN_FALSE;
1756 				} else {
1757 					flag_expected = getopt_result & PHP_MECAB_GETOPT_FLAG_EXPECTED;
1758 					path_expected = getopt_result & PHP_MECAB_GETOPT_PATH_EXPECTED;
1759 					if (getopt_result & PHP_MECAB_GETOPT_RCFILE_EXPECTED) {
1760 						resolved_path = rcfile_buf;
1761 					} else if (getopt_result & PHP_MECAB_GETOPT_DICDIR_EXPECTED) {
1762 						resolved_path = dicdir_buf;
1763 					} else if (getopt_result & PHP_MECAB_GETOPT_USERDIC_EXPECTED) {
1764 						resolved_path = userdic_buf;
1765 					}
1766 				}
1767 				argv[argc++] = key;
1768 				if (path_expected) {
1769 					PHP_MECAB_CHECK_FILE(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry));
1770 					argv[argc++] = resolved_path;
1771 				} else {
1772 					argv[argc++] = Z_STRVAL_PP(entry);
1773 				}
1774 				flag_expected = 1;
1775 				path_expected = 0;
1776 				break;
1777 
1778 			  case HASH_KEY_IS_LONG:
1779 				if (flag_expected) {
1780 					getopt_result = php_mecab_check_option(Z_STRVAL_PP(entry));
1781 					if (getopt_result == FAILURE) {
1782 						php_error_docref(NULL TSRMLS_CC, E_WARNING,
1783 								"Invalid option '%s' given", Z_STRVAL_PP(entry));
1784 						efree(argv);
1785 						RETURN_FALSE;
1786 					} else {
1787 						flag_expected = getopt_result & PHP_MECAB_GETOPT_FLAG_EXPECTED;
1788 						path_expected = getopt_result & PHP_MECAB_GETOPT_PATH_EXPECTED;
1789 						if (getopt_result & PHP_MECAB_GETOPT_RCFILE_EXPECTED) {
1790 							resolved_path = rcfile_buf;
1791 						} else if (getopt_result & PHP_MECAB_GETOPT_DICDIR_EXPECTED) {
1792 							resolved_path = dicdir_buf;
1793 						} else if (getopt_result & PHP_MECAB_GETOPT_USERDIC_EXPECTED) {
1794 							resolved_path = userdic_buf;
1795 						}
1796 					}
1797 					argv[argc++] = Z_STRVAL_PP(entry);
1798 				} else if (path_expected) {
1799 					PHP_MECAB_CHECK_FILE(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry));
1800 					argv[argc++] = resolved_path;
1801 				} else {
1802 					argv[argc++] = Z_STRVAL_PP(entry);
1803 				}
1804 				break;
1805 			}
1806 
1807 			zend_hash_move_forward(options);
1808 		}
1809 	} else {
1810 		argv = (char **)ecalloc(min_argc, sizeof(char *));
1811 	}
1812 
1813 	/* apply default options */
1814 	if (rcfile_buf[0] == '\0' && PHP_MECAB_CHECK_DEFAULT(rcfile)) {
1815 		size_t rcfile_len = strlen(MECAB_G(default_rcfile));
1816 		resolved_path = rcfile_buf;
1817 		*resolved_path++ = '-';
1818 		*resolved_path++ = 'r';
1819 		PHP_MECAB_CHECK_FILE(MECAB_G(default_rcfile), rcfile_len);
1820 		argv[argc++] = rcfile_buf;
1821 	}
1822 	if (dicdir_buf[0] == '\0' && PHP_MECAB_CHECK_DEFAULT(dicdir)) {
1823 		size_t dicdir_len = strlen(MECAB_G(default_dicdir));
1824 		resolved_path = dicdir_buf;
1825 		*resolved_path++ = '-';
1826 		*resolved_path++ = 'd';
1827 		PHP_MECAB_CHECK_FILE(MECAB_G(default_dicdir), dicdir_len);
1828 		argv[argc++] = dicdir_buf;
1829 	}
1830 	if (userdic_buf[0] == '\0' && PHP_MECAB_CHECK_DEFAULT(userdic)) {
1831 		size_t userdic_len = strlen(MECAB_G(default_userdic));
1832 		resolved_path = userdic_buf;
1833 		*resolved_path++ = '-';
1834 		*resolved_path++ = 'u';
1835 		PHP_MECAB_CHECK_FILE(MECAB_G(default_userdic), userdic_len);
1836 		argv[argc++] = userdic_buf;
1837 	}
1838 
1839 	/* create mecab object */
1840 	argv[0] = "mecab";
1841 	argv[argc] = NULL;
1842 	mecab = mecab_new(argc, argv);
1843 
1844 	efree(argv);
1845 	if (options != NULL) {
1846 		zend_hash_destroy(options);
1847 		FREE_HASHTABLE(options);
1848 	}
1849 
1850 	/* on error */
1851 	if (mecab == NULL) {
1852 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(NULL));
1853 		RETURN_FALSE;
1854 	}
1855 
1856 	if (object) {
1857 		php_mecab_object *intern;
1858 		PHP_MECAB_FETCH_OBJECT(intern, php_mecab_object *, object);
1859 		xmecab = intern->ptr;
1860 		if (xmecab->ptr != NULL) {
1861 			mecab_destroy(mecab);
1862 			zend_throw_exception(ext_ce_BadMethodCallException,
1863 					"MeCab already initialized", 0 TSRMLS_CC);
1864 			return;
1865 		}
1866 	} else {
1867 		xmecab = php_mecab_ctor(TSRMLS_C);
1868 		ZEND_REGISTER_RESOURCE(return_value, xmecab, le_mecab);
1869 	}
1870 	xmecab->ptr = mecab;
1871 }
1872 /* }}} mecab_new */
1873 
1874 /* {{{ proto void mecab_destroy(resource mecab mecab) */
1875 /**
1876  * void mecab mecab_destroy(resource mecab mecab)
1877  *
1878  * Free the tagger.
1879  *
1880  * @param	resource mecab	$mecab	The tagger resource of MeCab.
1881  * @return	void
1882  */
PHP_FUNCTION(mecab_destroy)1883 static PHP_FUNCTION(mecab_destroy)
1884 {
1885 	/* declaration of the arguments */
1886 	zval *zmecab = NULL;
1887 	php_mecab *mecab = NULL;
1888 
1889 	/* parse the arguments */
1890 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zmecab) == FAILURE) {
1891 		return;
1892 	}
1893 	ZEND_FETCH_RESOURCE(mecab, php_mecab *, &zmecab, -1, "mecab", le_mecab);
1894 
1895 	/* free the resource */
1896 	FREE_RESOURCE(zmecab);
1897 }
1898 /* }}} mecab_destroy */
1899 
1900 /* {{{ proto bool mecab_get_partial(resource mecab mecab) */
1901 /**
1902  * bool mecab_get_partial(resource mecab mecab)
1903  * bool MeCab_Tagger::getPartial()
1904  *
1905  * Get partial parsing mode.
1906  *
1907  * @param	resource mecab	$mecab	The tagger resource of MeCab.
1908  * @return	bool
1909  */
PHP_FUNCTION(mecab_get_partial)1910 static PHP_FUNCTION(mecab_get_partial)
1911 {
1912 	/* declaration of the resources */
1913 	zval *object = getThis();
1914 	zval *zmecab = NULL;
1915 	php_mecab *xmecab = NULL;
1916 	mecab_t *mecab = NULL;
1917 
1918 	/* parse the arguments */
1919 	PHP_MECAB_FROM_PARAMETER();
1920 
1921 	RETURN_BOOL(mecab_get_partial(mecab))
1922 }
1923 /* }}} */
1924 
1925 /* {{{ proto void mecab_set_partial(resource mecab mecab, bool partial) */
1926 /**
1927  * void mecab_set_partial(resource mecab mecab, bool partial)
1928  * void MeCab_Tagger::setPartial(bool partial)
1929  *
1930  * Set partial parsing mode.
1931  *
1932  * @param	resource mecab	$mecab	The tagger resource of MeCab.
1933  * @param	bool	$partial	The partial parsing mode.
1934  * @return	void
1935  */
PHP_FUNCTION(mecab_set_partial)1936 static PHP_FUNCTION(mecab_set_partial)
1937 {
1938 	/* declaration of the resources */
1939 	zval *object = getThis();
1940 	zval *zmecab = NULL;
1941 	php_mecab *xmecab = NULL;
1942 	mecab_t *mecab = NULL;
1943 
1944 	/* declaration of the arguments */
1945 	zend_bool partial = 0;
1946 
1947 	/* parse the arguments */
1948 	PHP_MECAB_PARSE_PARAMETERS("b", &partial);
1949 
1950 	mecab_set_partial(mecab, (int)partial);
1951 }
1952 /* }}} */
1953 
1954 /* {{{ proto float mecab_get_theta(resource mecab mecab) */
1955 /**
1956  * float mecab_get_theta(resource mecab mecab)
1957  * float MeCab_Tagger::getTheta()
1958  *
1959  * Get temparature parameter theta.
1960  *
1961  * @param	resource mecab	$mecab	The tagger resource of MeCab.
1962  * @return	float
1963  */
PHP_FUNCTION(mecab_get_theta)1964 static PHP_FUNCTION(mecab_get_theta)
1965 {
1966 	/* declaration of the resources */
1967 	zval *object = getThis();
1968 	zval *zmecab = NULL;
1969 	php_mecab *xmecab = NULL;
1970 	mecab_t *mecab = NULL;
1971 
1972 	/* parse the arguments */
1973 	PHP_MECAB_FROM_PARAMETER();
1974 
1975 	RETURN_DOUBLE((double)mecab_get_theta(mecab))
1976 }
1977 /* }}} */
1978 
1979 /* {{{ proto void mecab_(resource mecab mecab, float theta) */
1980 /**
1981  * void mecab_set_theta(resource mecab mecab, float theta)
1982  * void MeCab_Tagger::setTheta(float theta)
1983  *
1984  * Set temparature parameter theta.
1985  *
1986  * @param	resource mecab	$mecab	The tagger resource of MeCab.
1987  * @param	float	$theta	The temparature parameter theta.
1988  * @return	void
1989  */
PHP_FUNCTION(mecab_set_theta)1990 static PHP_FUNCTION(mecab_set_theta)
1991 {
1992 	/* declaration of the resources */
1993 	zval *object = getThis();
1994 	zval *zmecab = NULL;
1995 	php_mecab *xmecab = NULL;
1996 	mecab_t *mecab = NULL;
1997 
1998 	/* declaration of the arguments */
1999 	double theta = 0;
2000 
2001 	/* parse the arguments */
2002 	PHP_MECAB_PARSE_PARAMETERS("d", &theta);
2003 
2004 	mecab_set_theta(mecab, (float)theta);
2005 }
2006 /* }}} */
2007 
2008 /* {{{ proto int mecab_get_lattice_level(resource mecab mecab) */
2009 /**
2010  * int mecab_get_lattice_level(resource mecab mecab)
2011  * int MeCab_Tagger::getLatticeLevel()
2012  *
2013  * Get lattice information level.
2014  *
2015  * @param	resource mecab	$mecab	The tagger resource of MeCab.
2016  * @return	int
2017  */
PHP_FUNCTION(mecab_get_lattice_level)2018 static PHP_FUNCTION(mecab_get_lattice_level)
2019 {
2020 	/* declaration of the resources */
2021 	zval *object = getThis();
2022 	zval *zmecab = NULL;
2023 	php_mecab *xmecab = NULL;
2024 	mecab_t *mecab = NULL;
2025 
2026 	/* parse the arguments */
2027 	PHP_MECAB_FROM_PARAMETER();
2028 
2029 	RETURN_LONG((long)mecab_get_lattice_level(mecab))
2030 }
2031 /* }}} */
2032 
2033 /* {{{ proto void mecab_set_lattice_level(resource mecab mecab, int level) */
2034 /**
2035  * void mecab_set_lattice_level(resource mecab mecab, int level)
2036  * void MeCab_Tagger::setLatticeLevel(int level)
2037  *
2038  * Set lattice information level.
2039  *
2040  * @param	resource mecab	$mecab	The tagger resource of MeCab.
2041  * @param	int	$level	The lattice information level.
2042  * @return	void
2043  */
PHP_FUNCTION(mecab_set_lattice_level)2044 static PHP_FUNCTION(mecab_set_lattice_level)
2045 {
2046 	/* declaration of the resources */
2047 	zval *object = getThis();
2048 	zval *zmecab = NULL;
2049 	php_mecab *xmecab = NULL;
2050 	mecab_t *mecab = NULL;
2051 
2052 	/* declaration of the arguments */
2053 	long level = 0L;
2054 
2055 	/* parse the arguments */
2056 	PHP_MECAB_PARSE_PARAMETERS("l", &level);
2057 
2058 	mecab_set_lattice_level(mecab, (int)level);
2059 }
2060 /* }}} */
2061 
2062 /* {{{ proto bool mecab_get_all_morphs(resource mecab mecab) */
2063 /**
2064  * bool mecab_get_all_morphs(resource mecab mecab)
2065  * bool MeCab_Tagger::getAllMorphs()
2066  *
2067  * Get all morphs mode.
2068  *
2069  * @param	resource mecab	$mecab	The tagger resource of MeCab.
2070  * @return	bool
2071  */
PHP_FUNCTION(mecab_get_all_morphs)2072 static PHP_FUNCTION(mecab_get_all_morphs)
2073 {
2074 	/* declaration of the resources */
2075 	zval *object = getThis();
2076 	zval *zmecab = NULL;
2077 	php_mecab *xmecab = NULL;
2078 	mecab_t *mecab = NULL;
2079 
2080 	/* parse the arguments */
2081 	PHP_MECAB_FROM_PARAMETER();
2082 
2083 	RETURN_BOOL(mecab_get_all_morphs(mecab))
2084 }
2085 /* }}} */
2086 
2087 /* {{{ proto void mecab_set_all_morphs(resource mecab mecab, int all_morphs) */
2088 /**
2089  * void mecab_set_all_morphs(resource mecab mecab, int all_morphs)
2090  * void MeCab_Tagger::setAllMorphs(int all_morphs)
2091  *
2092  * Set all morphs mode.
2093  *
2094  * @param	resource mecab	$mecab	The tagger resource of MeCab.
2095  * @param	bool	$all_morphs	The all morphs mode.
2096  * @return	void
2097  */
PHP_FUNCTION(mecab_set_all_morphs)2098 static PHP_FUNCTION(mecab_set_all_morphs)
2099 {
2100 	/* declaration of the resources */
2101 	zval *object = getThis();
2102 	zval *zmecab = NULL;
2103 	php_mecab *xmecab = NULL;
2104 	mecab_t *mecab = NULL;
2105 
2106 	/* declaration of the arguments */
2107 	zend_bool all_morphs = 0;
2108 
2109 	/* parse the arguments */
2110 	PHP_MECAB_PARSE_PARAMETERS("b", &all_morphs);
2111 
2112 	mecab_set_all_morphs(mecab, (int)all_morphs);
2113 }
2114 /* }}} */
2115 
2116 /* {{{ proto string mecab_sparse_tostr(resource mecab mecab, string str[, int len[, int olen]]) */
2117 /**
2118  * string mecab_sparse_tostr(resource mecab mecab, string str[, int len[, int olen]])
2119  * string MeCab_Tagger::parse(string str[, int len[, int olen]])
2120  * string MeCab_Tagger::parseToString(string str[, int len[, int olen]])
2121  *
2122  * Get the parse result as a string.
2123  *
2124  * @param	resource mecab	$mecab	The tagger resource of MeCab.
2125  * @param	string	$str	The parse target.
2126  * @param	int	$len	The maximum length that can be analyzed. (optional)
2127  * @param	int	$olen	The limit length of the output buffer. (optional)
2128  * @return	string	The parse result.
2129  *					If output buffer has overflowed, returns false.
2130  */
PHP_FUNCTION(mecab_sparse_tostr)2131 static PHP_FUNCTION(mecab_sparse_tostr)
2132 {
2133 	/* declaration of the resources */
2134 	zval *object = getThis();
2135 	zval *zmecab = NULL;
2136 	php_mecab *xmecab = NULL;
2137 	mecab_t *mecab = NULL;
2138 
2139 	/* declaration of the arguments */
2140 	const char *str = NULL;
2141 	int str_len = 0;
2142 	long len = 0;
2143 	long olen = 0;
2144 
2145 	/* declaration of the local variables */
2146 	size_t ilen = 0;
2147 	char *ostr = NULL;
2148 	zend_bool ostr_free = 0;
2149 
2150 	/* parse the arguments */
2151 	PHP_MECAB_PARSE_PARAMETERS("s|ll", &str, &str_len, &len, &olen);
2152 
2153 	/* call mecab_sparse_tostr() */
2154 	php_mecab_set_string(xmecab, str, str_len TSRMLS_CC);
2155 	ilen = (size_t)((len > 0) ? MIN(len, (long)str_len) : str_len);
2156 	if (olen == 0) {
2157 		ostr = (char *)mecab_sparse_tostr2(mecab, xmecab->str, ilen);
2158 	} else {
2159 		ostr = (char *)emalloc((size_t)olen + 1);
2160 		ostr = mecab_sparse_tostr3(mecab, xmecab->str, ilen, ostr, (size_t)olen);
2161 		ostr_free = 1;
2162 	}
2163 
2164 	/* set return value */
2165 	if (ostr == NULL) {
2166 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
2167 		RETVAL_FALSE;
2168 	} else {
2169 		RETVAL_STRING(ostr, 1);
2170 	}
2171 
2172 	/* free */
2173 	if (ostr_free) {
2174 		efree(ostr);
2175 	}
2176 }
2177 /* }}} mecab_sparse_tostr */
2178 
2179 /* {{{ proto resource mecab_node mecab_sparse_tonode(resource mecab mecab, string str[, int len]) */
2180 /**
2181  * resource mecab_node mecab_sparse_tonode(resource mecab mecab, string str[, int len])
2182  * object MeCab_Node MeCab_Tagger::parseToNode(string str[, int len])
2183  *
2184  * Get the parse result as a node.
2185  *
2186  * @param	resource mecab	$mecab	The tagger resource of MeCab.
2187  * @param	string	$str	The parse target.
2188  * @param	int	$len	The maximum length that can be analyzed. (optional)
2189  * @return	resource mecab_node	The result node of given string.
2190  */
PHP_FUNCTION(mecab_sparse_tonode)2191 static PHP_FUNCTION(mecab_sparse_tonode)
2192 {
2193 	/* declaration of the resources */
2194 	zval *object = getThis();
2195 	zval *zmecab = NULL;
2196 	php_mecab *xmecab = NULL;
2197 	mecab_t *mecab = NULL;
2198 
2199 	/* declaration of the arguments */
2200 	const char *str = NULL;
2201 	int str_len = 0;
2202 	long len = 0;
2203 
2204 	/* declaration of the local variables */
2205 	size_t ilen = 0;
2206 	const mecab_node_t *node = NULL;
2207 	php_mecab_node *xnode = NULL;
2208 
2209 	/* parse the arguments */
2210 	PHP_MECAB_PARSE_PARAMETERS("s|l", &str, &str_len, &len);
2211 
2212 	/* call mecab_sparse_tonode() */
2213 	php_mecab_set_string(xmecab, str, str_len TSRMLS_CC);
2214 	ilen = (size_t)((len > 0) ? MIN(len, (long)str_len) : str_len);
2215 	node = mecab_sparse_tonode2(mecab, xmecab->str, ilen);
2216 	if (node == NULL) {
2217 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
2218 		RETURN_FALSE;
2219 	}
2220 
2221 	/* set return value */
2222 	if (object) {
2223 		php_mecab_node_object *newobj;
2224 		object_init_ex(return_value, ce_MeCab_Node);
2225 		PHP_MECAB_FETCH_OBJECT(newobj, php_mecab_node_object *, return_value);
2226 		xnode = newobj->ptr;
2227 	} else {
2228 		xnode = php_mecab_node_ctor(TSRMLS_C);
2229 		ZEND_REGISTER_RESOURCE(return_value, xnode, le_mecab_node);
2230 	}
2231 	xnode->ptr = node;
2232 	php_mecab_node_set_tagger(xnode, xmecab TSRMLS_CC);
2233 }
2234 /* }}} mecab_sparse_tonode */
2235 
2236 /* {{{ proto string mecab_nbest_sparse_tostr(resource mecab mecab, int n, string str[, int len[, int olen]]) */
2237 /**
2238  * string mecab_nbest_sparse_tostr(resource mecab mecab, int n, string str[, int len[, int olen]])
2239  * string MeCab_Tagger::parseNBest(int n, string str[, int len[, int olen]])
2240  *
2241  * Get the N-Best list as a string.
2242  *
2243  * @param	resource mecab	$mecab	The tagger resource of MeCab.
2244  * @param	int	$n	The number of the result list.
2245  * @param	string	$str	The parse target.
2246  * @param	int	$len	The maximum length that can be analyzed. (optional)
2247  * @param	int	$olen	The maximum length of the output. (optional)
2248  * @return	string	The N-Best list.
2249  *					If output buffer has overflowed, returns false.
2250  */
PHP_FUNCTION(mecab_nbest_sparse_tostr)2251 static PHP_FUNCTION(mecab_nbest_sparse_tostr)
2252 {
2253 	/* declaration of the resources */
2254 	zval *object = getThis();
2255 	zval *zmecab = NULL;
2256 	php_mecab *xmecab = NULL;
2257 	mecab_t *mecab = NULL;
2258 
2259 	/* declaration of the arguments */
2260 	long n = 0;
2261 	const char *str = NULL;
2262 	int str_len = 0;
2263 	long len = 0;
2264 	long olen = 0;
2265 
2266 	/* declaration of the local variables */
2267 	size_t ilen = 0;
2268 	char *ostr = NULL;
2269 	zend_bool ostr_free = 1;
2270 
2271 	/* parse the arguments */
2272 	PHP_MECAB_PARSE_PARAMETERS("ls|ll", &n, &str, &str_len, &len, &olen);
2273 
2274 	/* call mecab_nbest_sparse_tostr() */
2275 	php_mecab_set_string(xmecab, str, str_len TSRMLS_CC);
2276 	ilen = (size_t)((len > 0) ? MIN(len, (long)str_len) : str_len);
2277 	if (olen == 0) {
2278 		ostr = (char *)mecab_nbest_sparse_tostr2(mecab, n, xmecab->str, ilen);
2279 	} else {
2280 		ostr = (char *)emalloc(olen + 1);
2281 		ostr = mecab_nbest_sparse_tostr3(mecab, n, xmecab->str, ilen, ostr, (size_t)olen);
2282 		ostr_free = 1;
2283 	}
2284 
2285 	/* set return value */
2286 	if (ostr == NULL) {
2287 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
2288 		RETVAL_FALSE;
2289 	} else {
2290 		RETVAL_STRING(ostr, 1);
2291 	}
2292 
2293 	/* free */
2294 	if (ostr_free) {
2295 		efree(ostr);
2296 	}
2297 }
2298 /* }}} mecab_nbest_sparse_tostr */
2299 
2300 /* {{{ proto bool mecab_nbest_init(resource mecab mecab, string str[, int len]) */
2301 /**
2302  * bool mecab_nbest_init(resource mecab mecab, string str[, int len])
2303  * bool MeCab_Tagger::parseNBestInit(string str[, int len])
2304  *
2305  * Initialize the N-Best list.
2306  *
2307  * @param	resource mecab	$mecab	The tagger resource of MeCab.
2308  * @param	string	$str	The parse target.
2309  * @param	int	$len	The maximum length that can be analyzed. (optional)
2310  * @return	bool	True if succeeded to initilalize, otherwise returns false.
2311  */
PHP_FUNCTION(mecab_nbest_init)2312 static PHP_FUNCTION(mecab_nbest_init)
2313 {
2314 	/* declaration of the resources */
2315 	zval *object = getThis();
2316 	zval *zmecab = NULL;
2317 	php_mecab *xmecab = NULL;
2318 	mecab_t *mecab = NULL;
2319 
2320 	/* declaration of the arguments */
2321 	const char *str = NULL;
2322 	int str_len = 0;
2323 	long len = 0;
2324 
2325 	/* declaration of the local variables */
2326 	size_t ilen = 0;
2327 	int result = 0;
2328 
2329 	/* parse the arguments */
2330 	PHP_MECAB_PARSE_PARAMETERS("s|l", &str, &str_len, &len);
2331 
2332 	/* call mecab_nbest_init() */
2333 	php_mecab_set_string(xmecab, str, str_len TSRMLS_CC);
2334 	ilen = (size_t)((len > 0) ? MIN(len, (long)str_len) : str_len);
2335 	result = mecab_nbest_init2(mecab, xmecab->str, ilen);
2336 	if (result == 0) {
2337 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
2338 		RETURN_FALSE;
2339 	}
2340 	RETURN_TRUE;
2341 }
2342 /* }}} mecab_nbest_init */
2343 
2344 /* {{{ proto string mecab_nbest_next_tostr(resource mecab mecab[, int olen]) */
2345 /**
2346  * string mecab_nbest_next_tostr(resource mecab mecab[, int olen])
2347  * string MeCab_Tagger::next([int olen]])
2348  *
2349  * Get the next result of N-Best as a string.
2350  *
2351  * @param	resource mecab	$mecab	The tagger resource of MeCab.
2352  * @param	int	$olen	The maximum length of the output. (optional)
2353  * @return	string	The parse result of the next pointer.
2354  *					If there are no more results, returns false.
2355  *					Also returns false if output buffer has overflowed.
2356  */
PHP_FUNCTION(mecab_nbest_next_tostr)2357 static PHP_FUNCTION(mecab_nbest_next_tostr)
2358 {
2359 	/* declaration of the resources */
2360 	zval *object = getThis();
2361 	zval *zmecab = NULL;
2362 	php_mecab *xmecab = NULL;
2363 	mecab_t *mecab = NULL;
2364 
2365 	/* declaration of the arguments */
2366 	long olen = 0;
2367 
2368 	/* declaration of the local variables */
2369 	char *ostr = NULL;
2370 	zend_bool ostr_free = 0;
2371 	const char *what = NULL;
2372 
2373 	/* parse the arguments */
2374 	PHP_MECAB_PARSE_PARAMETERS("|l", &olen);
2375 
2376 	/* call mecab_nbest_sparse_tostr() */
2377 	if (olen == 0) {
2378 		ostr = (char *)mecab_nbest_next_tostr(mecab);
2379 	} else {
2380 		ostr = (char *)emalloc(olen + 1);
2381 		ostr = mecab_nbest_next_tostr2(mecab, ostr, (size_t)olen);
2382 		ostr_free = 1;
2383 	}
2384 
2385 	/* set return value */
2386 	if (ostr == NULL) {
2387 		if ((what = mecab_strerror(mecab)) != NULL &&
2388 			strcmp((char *)what, "no more results"))
2389 		{
2390 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", what);
2391 		}
2392 		RETVAL_FALSE;
2393 	} else {
2394 		RETVAL_STRING(ostr, 1);
2395 	}
2396 
2397 	/* free */
2398 	if (ostr_free) {
2399 		efree(ostr);
2400 	}
2401 }
2402 /* }}} mecab_nbest_next_tostr */
2403 
2404 /* {{{ proto resource mecab_node mecab_nbest_next_tonode(resource mecab mecab) */
2405 /**
2406  * resource mecab_node mecab_nbest_next_tonode(resource mecab mecab)
2407  * object MeCab_Node MeCab_Tagger::nextNode(void)
2408  *
2409  * Get the next result of N-Best as a node.
2410  *
2411  * @param	resource mecab	$mecab	The tagger resource of MeCab.
2412  * @return	resource mecab_node	The result node of the next pointer.
2413  *								If there are no more results, returns false.
2414  */
PHP_FUNCTION(mecab_nbest_next_tonode)2415 static PHP_FUNCTION(mecab_nbest_next_tonode)
2416 {
2417 	/* declaration of the resources */
2418 	zval *object = getThis();
2419 	zval *zmecab = NULL;
2420 	php_mecab *xmecab = NULL;
2421 	mecab_t *mecab = NULL;
2422 
2423 	/* declaration of the local variables */
2424 	const mecab_node_t *node = NULL;
2425 	php_mecab_node *xnode = NULL;
2426 	const char *what = NULL;
2427 
2428 	/* parse the arguments */
2429 	PHP_MECAB_FROM_PARAMETER();
2430 
2431 	/* call mecab_nbest_next_tonode() */
2432 	node = mecab_nbest_next_tonode(mecab);
2433 	if (node == NULL) {
2434 		if ((what = mecab_strerror(mecab)) != NULL &&
2435 			strcmp((char *)what, "no more results"))
2436 		{
2437 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", what);
2438 		}
2439 		RETURN_FALSE;
2440 	}
2441 
2442 	/* set return value */
2443 	if (object) {
2444 		php_mecab_node_object *newobj;
2445 		object_init_ex(return_value, ce_MeCab_Node);
2446 		PHP_MECAB_FETCH_OBJECT(newobj, php_mecab_node_object *, return_value);
2447 		xnode = newobj->ptr;
2448 	} else {
2449 		xnode = php_mecab_node_ctor(TSRMLS_C);
2450 		ZEND_REGISTER_RESOURCE(return_value, xnode, le_mecab_node);
2451 	}
2452 	xnode->ptr = node;
2453 	php_mecab_node_set_tagger(xnode, xmecab TSRMLS_CC);
2454 }
2455 /* }}} mecab_nbest_next_tonode */
2456 
2457 /* {{{ proto string mecab_format_node(resource mecab mecab, resource mecab_node node) */
2458 /**
2459  * string mecab_format_node(resource mecab mecab, resource mecab_node node)
2460  * string MeCab_Tagger::formatNode(object MeCab_Node node)
2461  *
2462  * Format a node to string.
2463  * The format is specified by "-O" option or --{node|unk|bos|eos}-format=STR.
2464  * The detail is found in the web site and/or the manpage of MeCab.
2465  * NOTICE: If the option was "wakati" or "dump", the return string will be empty.
2466  *
2467  * @param	resource mecab	$mecab	The tagger resource of MeCab.
2468  * @param	resource mecab_node	$node	The node of the source string.
2469  * @return	string	The formatted string.
2470  * @see	mecab_node_tostring
2471  */
PHP_FUNCTION(mecab_format_node)2472 static PHP_FUNCTION(mecab_format_node)
2473 {
2474 	/* declaration of the resources */
2475 	zval *object = getThis();
2476 	zval *node_object = NULL;
2477 	zval *zmecab = NULL;
2478 	zval *znode = NULL;
2479 	php_mecab *xmecab = NULL;
2480 	php_mecab_node *xnode = NULL;
2481 	mecab_t *mecab = NULL;
2482 	const mecab_node_t *node = NULL;
2483 
2484 	/* declaration of the local variables */
2485 	const char *fmt = NULL;
2486 
2487 	/* parse the arguments */
2488 	if (object) {
2489 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &node_object, ce_MeCab_Node) == FAILURE) {
2490 			return;
2491 		} else {
2492 			php_mecab_object *intern;
2493 			php_mecab_node_object *intern_node;
2494 			PHP_MECAB_FETCH_OBJECT(intern, php_mecab_object *, object);
2495 			PHP_MECAB_FETCH_OBJECT(intern_node, php_mecab_node_object *, node_object);
2496 			xmecab = intern->ptr;
2497 			xnode = intern_node->ptr;
2498 		}
2499 	} else {
2500 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &zmecab, &znode) == FAILURE) {
2501 			return;
2502 		}
2503 		ZEND_FETCH_RESOURCE(xmecab, php_mecab *, &zmecab, -1, "mecab", le_mecab);
2504 		ZEND_FETCH_RESOURCE(xnode, php_mecab_node *, &znode, -1, "mecab_node", le_mecab_node);
2505 	}
2506 	mecab = xmecab->ptr;
2507 	node = xnode->ptr;
2508 
2509 	/* call mecab_format_node() */
2510 	fmt = mecab_format_node(mecab, node);
2511 	if (fmt == NULL) {
2512 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
2513 		RETURN_FALSE;
2514 	}
2515 
2516 	/* set return value */
2517 	RETURN_STRING((char *)fmt, 1);
2518 }
2519 /* }}} mecab_format_node */
2520 
2521 /* {{{ proto array mecab_dictionary_info(resource mecab mecab) */
2522 /**
2523  * array mecab_dictionary_info(resource mecab mecab)
2524  * array MeCab_Tagger::dictionaryInfo(void)
2525  *
2526  * Get the information of using dictionary as an associative array.
2527  *
2528  * @return	array	The information of the dictionary.
2529  */
PHP_FUNCTION(mecab_dictionary_info)2530 static PHP_FUNCTION(mecab_dictionary_info)
2531 {
2532 	/* declaration of the resources */
2533 	zval *object = getThis();
2534 	zval *zmecab = NULL;
2535 	php_mecab *xmecab = NULL;
2536 	mecab_t *mecab = NULL;
2537 
2538 	/* declaration of the local variables */
2539 	const mecab_dictionary_info_t *dicinfo = NULL;
2540 
2541 	/* parse the arguments */
2542 	PHP_MECAB_FROM_PARAMETER();
2543 
2544 	/* get dictionary information */
2545 	dicinfo = mecab_dictionary_info(mecab);
2546 	if (dicinfo == NULL) {
2547 		RETURN_NULL();
2548 	}
2549 
2550 	/* initialize */
2551 	array_init(return_value);
2552 
2553 	/* get information for each dictionary */
2554 	while (dicinfo != NULL) {
2555 		zval *tmp = NULL;
2556 
2557 		MAKE_STD_ZVAL(tmp);
2558 		array_init(tmp);
2559 
2560 		add_assoc_string(tmp, "filename", (char *)dicinfo->filename, 1);
2561 		add_assoc_string(tmp, "charset",  (char *)dicinfo->charset,  1);
2562 		add_assoc_long(tmp, "size",    (long)dicinfo->size);
2563 		add_assoc_long(tmp, "type",    (long)dicinfo->type);
2564 		add_assoc_long(tmp, "lsize",   (long)dicinfo->lsize);
2565 		add_assoc_long(tmp, "rsize",   (long)dicinfo->rsize);
2566 		add_assoc_long(tmp, "version", (long)dicinfo->version);
2567 
2568 		add_next_index_zval(return_value, tmp);
2569 
2570 		dicinfo = dicinfo->next;
2571 	}
2572 }
2573 /* }}} mecab_dictionary_info */
2574 
2575 /* {{{ proto array mecab_node_toarray(resource mecab_node node[, bool dump_all]) */
2576 /**
2577  * array mecab_node_toarray(resource mecab_node node[, bool dump_all])
2578  * array MeCab_Node::toArray([bool dump_all])
2579  *
2580  * Get all elements of the node as an associative array.
2581  *
2582  * @param	resource mecab_node	$node	The node of the source string.
2583  * @param	bool	$dump_all	Whether dump all related nodes and paths or not.
2584  * @return	array	All elements of the node.
2585  */
PHP_FUNCTION(mecab_node_toarray)2586 static PHP_FUNCTION(mecab_node_toarray)
2587 {
2588 	/* declaration of the resources */
2589 	zval *object = getThis();
2590 	zval *znode = NULL;
2591 	php_mecab_node *xnode = NULL;
2592 	const mecab_node_t *node = NULL;
2593 
2594 	/* declaration of the arguments */
2595 	zend_bool dump_all = 0;
2596 
2597 	/* parse the arguments */
2598 	PHP_MECAB_NODE_PARSE_PARAMETERS("|b", &dump_all);
2599 
2600 	/* initialize */
2601 	array_init(return_value);
2602 
2603 	/* assign siblings and paths */
2604 	if (dump_all) {
2605 		add_assoc_zval(return_value, "prev",  php_mecab_node_get_sibling(NULL, object, xnode, NODE_PREV TSRMLS_CC));
2606 		add_assoc_zval(return_value, "next",  php_mecab_node_get_sibling(NULL, object, xnode, NODE_NEXT TSRMLS_CC));
2607 		add_assoc_zval(return_value, "enext", php_mecab_node_get_sibling(NULL, object, xnode, NODE_ENEXT TSRMLS_CC));
2608 		add_assoc_zval(return_value, "bnext", php_mecab_node_get_sibling(NULL, object, xnode, NODE_BNEXT TSRMLS_CC));
2609 		add_assoc_zval(return_value, "rpath", php_mecab_node_get_path(NULL, object, xnode, NODE_RPATH TSRMLS_CC));
2610 		add_assoc_zval(return_value, "lpath", php_mecab_node_get_path(NULL, object, xnode, NODE_LPATH TSRMLS_CC));
2611 	}
2612 
2613 	/* assign node info */
2614 	add_assoc_stringl(return_value, "surface", (char *)node->surface, (int)node->length, 1);
2615 	add_assoc_string(return_value,  "feature", (char *)node->feature, 1);
2616 	add_assoc_long(return_value, "id",         (long)node->id);
2617 	add_assoc_long(return_value, "length",     (long)node->length);
2618 	add_assoc_long(return_value, "rlength",    (long)node->rlength);
2619 	add_assoc_long(return_value, "rcAttr",     (long)node->rcAttr);
2620 	add_assoc_long(return_value, "lcAttr",     (long)node->lcAttr);
2621 	add_assoc_long(return_value, "posid",      (long)node->posid);
2622 	add_assoc_long(return_value, "char_type",  (long)node->char_type);
2623 	add_assoc_long(return_value, "stat",       (long)node->stat);
2624 	add_assoc_bool(return_value, "isbest",     (long)node->isbest);
2625 	add_assoc_double(return_value, "alpha", (double)node->alpha);
2626 	add_assoc_double(return_value, "beta",  (double)node->beta);
2627 	add_assoc_double(return_value, "prob",  (double)node->prob);
2628 	add_assoc_long(return_value,   "wcost", (long)node->wcost);
2629 	add_assoc_long(return_value,   "cost",  (long)node->cost);
2630 }
2631 /* }}} mecab_node_toarray */
2632 
2633 /* {{{ proto string mecab_node_tostring(resource mecab_node node) */
2634 /**
2635  * string mecab_node_tostring(resource mecab_node node)
2636  * string MeCab_Node::toString(void)
2637  * string MeCab_Node::__toString(void)
2638  *
2639  * Get the formatted string of the node.
2640  *
2641  * @param	resource mecab_node	$node	The node of the source string.
2642  * @return	string	The formatted string.
2643  * @see	mecab_format_node
2644  */
PHP_FUNCTION(mecab_node_tostring)2645 static PHP_FUNCTION(mecab_node_tostring)
2646 {
2647 	/* declaration of the resources */
2648 	zval *object = getThis();
2649 	zval *znode = NULL;
2650 	php_mecab_node *xnode = NULL;
2651 	const mecab_node_t *node = NULL;
2652 
2653 	/* local variables */
2654 	mecab_t *mecab = NULL;
2655 	const char *fmt = NULL;
2656 
2657 	/* parse the arguments */
2658 	PHP_MECAB_NODE_FROM_PARAMETER();
2659 
2660 	/* call mecab_format_node() */
2661 	mecab = xnode->tagger->ptr;
2662 	fmt = mecab_format_node(mecab, node);
2663 	if (fmt == NULL) {
2664 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
2665 		RETURN_FALSE;
2666 	}
2667 
2668 	/* set return value */
2669 	RETURN_STRING((char *)fmt, 1);
2670 }
2671 /* }}} mecab_node_tostring */
2672 
2673 /* {{{ proto resource mecab_node mecab_node_prev(resource mecab_node node) */
2674 /**
2675  * resource mecab_node mecab_node_prev(resource mecab_node node)
2676  * object MeCab_Node MeCab_Node::getPrev(void)
2677  *
2678  * Get the previous node.
2679  *
2680  * @param	resource mecab_node	$node	The node of the source string.
2681  * @return	resource mecab_node	The previous node.
2682  *								If the given node is the first one, returns FALSE.
2683  */
PHP_FUNCTION(mecab_node_prev)2684 static PHP_FUNCTION(mecab_node_prev)
2685 {
2686 	php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, NODE_PREV);
2687 }
2688 /* }}} mecab_node_prev */
2689 
2690 /* {{{ proto resource mecab_node mecab_node_next(resource mecab_node node) */
2691 /**
2692  * resource mecab_node mecab_node_next(resource mecab_node node)
2693  * object MeCab_Node MeCab_Node::getNext(void)
2694  *
2695  * Get the next node.
2696  *
2697  * @param	resource mecab_node	$node	The node of the source string.
2698  * @return	resource mecab_node	The next node.
2699  *								If the given node is the last one, returns FALSE.
2700  */
PHP_FUNCTION(mecab_node_next)2701 static PHP_FUNCTION(mecab_node_next)
2702 {
2703 	php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, NODE_NEXT);
2704 }
2705 /* }}} mecab_node_next */
2706 
2707 /* {{{ proto resource mecab_node mecab_node_enext(resource mecab_node node) */
2708 /**
2709  * resource mecab_node mecab_node_enext(resource mecab_node node)
2710  * object MeCab_Node MeCab_Node::getENext(void)
2711  *
2712  * Get the enext node.
2713  *
2714  * @param	resource mecab_node	$node	The node of the source string.
2715  * @return	resource mecab_node	The next node which has same end point as the given node.
2716  *								If there is no `enext' node, returns false.
2717  */
PHP_FUNCTION(mecab_node_enext)2718 static PHP_FUNCTION(mecab_node_enext)
2719 {
2720 	php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, NODE_ENEXT);
2721 }
2722 /* }}} mecab_node_enext */
2723 
2724 /* {{{ proto resource mecab_node mecab_node_bnext(resource mecab_node node) */
2725 /**
2726  * resource mecab_node mecab_node_bnext(resource mecab_node node)
2727  * object MeCab_Node MeCab_Node::getBNext(void)
2728  *
2729  * Get the bnext node.
2730  *
2731  * @param	resource mecab_node	$node	The node of the source string.
2732  * @return	resource mecab_node	The next node which has same beggining point as the given one.
2733  *								If there is no `bnext' node, returns false.
2734  */
PHP_FUNCTION(mecab_node_bnext)2735 static PHP_FUNCTION(mecab_node_bnext)
2736 {
2737 	php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, NODE_BNEXT);
2738 }
2739 /* }}} mecab_node_bnext */
2740 
2741 /* {{{ proto resource mecab_path mecab_node_rpath(resource mecab_node node) */
2742 /**
2743  * resource mecab_path mecab_node_rpath(resource mecab_node node)
2744  * object MeCab_Path MeCab_Node::getRPath(void)
2745  *
2746  * Get the rpath.
2747  *
2748  * @param	resource mecab_node	$node	The node of the source string.
2749  * @return	resource mecab_path	The next node which has same end point as the given node.
2750  *								If there is no `rpath' node, returns false.
2751  */
PHP_FUNCTION(mecab_node_rpath)2752 static PHP_FUNCTION(mecab_node_rpath)
2753 {
2754 	php_mecab_node_get_path_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, NODE_RPATH);
2755 }
2756 /* }}} mecab_node_rpath */
2757 
2758 /* {{{ proto resource mecab_path mecab_node_lpath(resource mecab_node node) */
2759 /**
2760  * resource mecab_path mecab_node_lpath(resource mecab_node node)
2761  * object MeCab_Path MeCab_Node::getLPath(void)
2762  *
2763  * Get the lpath.
2764  *
2765  * @param	resource mecab_node	$node	The node of the source string.
2766  * @return	resource mecab_path	The next node which has same beggining point as the given one.
2767  *								If there is no `lpath' node, returns false.
2768  */
PHP_FUNCTION(mecab_node_lpath)2769 static PHP_FUNCTION(mecab_node_lpath)
2770 {
2771 	php_mecab_node_get_path_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, NODE_LPATH);
2772 }
2773 /* }}} mecab_node_lpath */
2774 
2775 /* {{{ proto string mecab_node_surface(resource mecab_node node) */
2776 /**
2777  * string mecab_node_surface(resource mecab_node node)
2778  * string MeCab_Node::getSurface(void)
2779  *
2780  * Get the surface.
2781  *
2782  * @param	resource mecab_node	$node	The node of the source string.
2783  * @return	string	The surface of the node.
2784  */
PHP_FUNCTION(mecab_node_surface)2785 static PHP_FUNCTION(mecab_node_surface)
2786 {
2787 	PHP_MECAB_NODE_RETURN_PROPERTY(STRINGL, (char *)node->surface, (int)node->length, 1);
2788 }
2789 /* }}} mecab_node_surface */
2790 
2791 /* {{{ proto string mecab_node_feature(resource mecab_node node) */
2792 /**
2793  * string mecab_node_feature(resource mecab_node node)
2794  * string MeCab_Node::getFeature(void)
2795  *
2796  * Get the feature.
2797  *
2798  * @param	resource mecab_node	$node	The node of the source string.
2799  * @return	string	The feature of the node.
2800  */
PHP_FUNCTION(mecab_node_feature)2801 static PHP_FUNCTION(mecab_node_feature)
2802 {
2803 	PHP_MECAB_NODE_RETURN_PROPERTY(STRING, (char *)node->feature, 1);
2804 }
2805 /* }}} mecab_node_feature */
2806 
2807 /* {{{ proto int mecab_node_id(resource mecab_node node) */
2808 /**
2809  * int mecab_node_id(resource mecab_node node)
2810  * int MeCab_Node::getId(void)
2811  *
2812  * Get the ID.
2813  *
2814  * @param	resource mecab_node	$node	The node of the source string.
2815  * @return	int	The ID of the node.
2816  */
PHP_FUNCTION(mecab_node_id)2817 static PHP_FUNCTION(mecab_node_id)
2818 {
2819 	PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->id);
2820 }
2821 /* }}} mecab_node_id */
2822 
2823 /* {{{ proto int mecab_node_length(resource mecab_node node) */
2824 /**
2825  * int mecab_node_length(resource mecab_node node)
2826  * int MeCab_Node::getLength(void)
2827  *
2828  * Get the length of the surface.
2829  *
2830  * @param	resource mecab_node	$node	The node of the source string.
2831  * @return	int	The length of the surface of the node.
2832  */
PHP_FUNCTION(mecab_node_length)2833 static PHP_FUNCTION(mecab_node_length)
2834 {
2835 	PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->length);
2836 }
2837 /* }}} mecab_node_length */
2838 
2839 /* {{{ proto int mecab_node_rlength(resource mecab_node node) */
2840 /**
2841  * int mecab_node_rlength(resource mecab_node node)
2842  * int MeCab_Node::getRLength(void)
2843  *
2844  * Get the length of the surface and its leading whitespace.
2845  *
2846  * @param	resource mecab_node	$node	The node of the source string.
2847  * @return	int	The length of the surface and its leading whitespace of the node.
2848  */
PHP_FUNCTION(mecab_node_rlength)2849 static PHP_FUNCTION(mecab_node_rlength)
2850 {
2851 	PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->rlength);
2852 }
2853 /* }}} mecab_node_rlength */
2854 
2855 /* {{{ proto int mecab_node_rcattr(resource mecab_node node) */
2856 /**
2857  * int mecab_node_rcattr(resource mecab_node node)
2858  * int MeCab_Node::getRcAttr(void)
2859  *
2860  * Get the ID of the right context.
2861  *
2862  * @param	resource mecab_node	$node	The node of the source string.
2863  * @return	int	The ID of the right context.
2864  */
PHP_FUNCTION(mecab_node_rcattr)2865 static PHP_FUNCTION(mecab_node_rcattr)
2866 {
2867 	PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->rcAttr);
2868 }
2869 /* }}} mecab_node_rcattr */
2870 
2871 /* {{{ proto int mecab_node_lcattr(resource mecab_node node) */
2872 /**
2873  * int mecab_node_lcattr(resource mecab_node node)
2874  * int MeCab_Node::getLcAttr(void)
2875  *
2876  * Get the ID of the left context.
2877  *
2878  * @param	resource mecab_node	$node	The node of the source string.
2879  * @return	int	The ID of the left context.
2880  */
PHP_FUNCTION(mecab_node_lcattr)2881 static PHP_FUNCTION(mecab_node_lcattr)
2882 {
2883 	PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->lcAttr);
2884 }
2885 /* }}} mecab_node_lcattr */
2886 
2887 /* {{{ proto int mecab_node_posid(resource mecab_node node) */
2888 /**
2889  * int mecab_node_posid(resource mecab_node node)
2890  * int MeCab_Node::getPosId(void)
2891  *
2892  * Get the ID of the Part-of-Speech.
2893  * (node->posid is not used in MeCab-0.90)
2894  *
2895  * @param	resource mecab_node	$node	The node of the source string.
2896  * @return	int	The ID of the Part-of-Speech.
2897  *				Currently, always returns 0.
2898  */
PHP_FUNCTION(mecab_node_posid)2899 static PHP_FUNCTION(mecab_node_posid)
2900 {
2901 	PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->posid);
2902 }
2903 /* }}} mecab_node_posid */
2904 
2905 /* {{{ proto int mecab_node_char_type(resource mecab_node node) */
2906 /**
2907  * int mecab_node_char_type(resource mecab_node node)
2908  * int MeCab_Node::getCharType(void)
2909  *
2910  * Get the type of the character.
2911  *
2912  * @param	resource mecab_node	$node	The node of the source string.
2913  * @return	int	The type of the character.
2914  */
PHP_FUNCTION(mecab_node_char_type)2915 static PHP_FUNCTION(mecab_node_char_type)
2916 {
2917 	PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->char_type);
2918 }
2919 /* }}} mecab_node_char_type */
2920 
2921 /* {{{ proto int mecab_node_stat(resource mecab_node node) */
2922 /**
2923  * int mecab_node_stat(resource mecab_node node)
2924  * int MeCab_Node::getStat(void)
2925  *
2926  * Get the status.
2927  *
2928  * @param	resource mecab_node	$node	The node of the source string.
2929  * @return	int	The status of the node.
2930  *				The return value is one of the following:
2931  *					MECAB_NOR_NODE (0:Normal)
2932  *					MECAB_UNK_NODE (1:Unknown)
2933  *					MECAB_BOS_NODE (2:Beginning-of-Sentence)
2934  *					MECAB_EOS_NODE (3:End-of-Sentence)
2935  */
PHP_FUNCTION(mecab_node_stat)2936 static PHP_FUNCTION(mecab_node_stat)
2937 {
2938 	PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->stat);
2939 }
2940 /* }}} mecab_node_stat */
2941 
2942 /* {{{ proto bool mecab_node_isbest(resource mecab_node node) */
2943 /**
2944  * bool mecab_node_isbest(resource mecab_node node)
2945  * bool MeCab_Node::isBest(void)
2946  *
2947  * Determine whether the node is the best solution.
2948  *
2949  * @param	resource mecab_node	$node	The node of the source string.
2950  * @return	bool	True if the node is the best, otherwise returns false.
2951  */
PHP_FUNCTION(mecab_node_isbest)2952 static PHP_FUNCTION(mecab_node_isbest)
2953 {
2954 	PHP_MECAB_NODE_RETURN_PROPERTY(BOOL, (node->isbest == 1));
2955 }
2956 /* }}} mecab_node_isbest */
2957 
2958 /* {{{ proto double mecab_node_alpha(resource mecab_node node) */
2959 /**
2960  * double mecab_node_alpha(resource mecab_node node)
2961  * double MeCab_Node::getAlpha(void)
2962  *
2963  * Get the forward log probability.
2964  *
2965  * @param	resource mecab_node	$node	The node of the source string.
2966  * @return	double	The forward log probability of the node.
2967  */
PHP_FUNCTION(mecab_node_alpha)2968 static PHP_FUNCTION(mecab_node_alpha)
2969 {
2970 	PHP_MECAB_NODE_RETURN_PROPERTY(DOUBLE, (double)node->alpha);
2971 }
2972 /* }}} mecab_node_alpha */
2973 
2974 /* {{{ proto double mecab_node_beta(resource mecab_node node) */
2975 /**
2976  * double mecab_node_beta(resource mecab_node node)
2977  * double MeCab_Node::getBeta(void)
2978  *
2979  * Get the backward log probability.
2980  *
2981  * @param	resource mecab_node	$node	The node of the source string.
2982  * @return	double	The backward log probability of the node.
2983  */
PHP_FUNCTION(mecab_node_beta)2984 static PHP_FUNCTION(mecab_node_beta)
2985 {
2986 	PHP_MECAB_NODE_RETURN_PROPERTY(DOUBLE, (double)node->beta);
2987 }
2988 /* }}} mecab_node_beta */
2989 
2990 /* {{{ proto double mecab_node_prob(resource mecab_node node) */
2991 /**
2992  * double mecab_node_prob(resource mecab_node node)
2993  * double MeCab_Node::getProb(void)
2994  *
2995  * Get the marginal probability.
2996  *
2997  * @param	resource mecab_node	$node	The node of the source string.
2998  * @return	double	The marginal probability of the node.
2999  */
PHP_FUNCTION(mecab_node_prob)3000 static PHP_FUNCTION(mecab_node_prob)
3001 {
3002 	PHP_MECAB_NODE_RETURN_PROPERTY(DOUBLE, (double)node->prob);
3003 }
3004 /* }}} mecab_node_prob */
3005 
3006 /* {{{ proto int mecab_node_wcost(resource mecab_node node) */
3007 /**
3008  * int mecab_node_wcost(resource mecab_node node)
3009  * int MeCab_Node::getWCost(void)
3010  *
3011  * Get the word arising cost.
3012  *
3013  * @param	resource mecab_node	$node	The node of the source string.
3014  * @return	int	The word arising cost of the node.
3015  */
PHP_FUNCTION(mecab_node_wcost)3016 static PHP_FUNCTION(mecab_node_wcost)
3017 {
3018 	PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->wcost);
3019 }
3020 /* }}} mecab_node_wcost */
3021 
3022 /* {{{ proto int mecab_node_cost(resource mecab_node node) */
3023 /**
3024  * int mecab_node_cost(resource mecab_node node)
3025  * int MeCab_Node::getCost(void)
3026  *
3027  * Get the cumulative cost.
3028  *
3029  * @param	resource mecab_node	$node	The node of the source string.
3030  * @return	int	The cumulative cost of the node.
3031  */
PHP_FUNCTION(mecab_node_cost)3032 static PHP_FUNCTION(mecab_node_cost)
3033 {
3034 	PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->cost);
3035 }
3036 /* }}} mecab_node_cost */
3037 
3038 /* {{{ proto resource mecab_path mecab_path_rnext(resource mecab_path path) */
3039 /**
3040  * resource mecab_path mecab_path_rnext(resource mecab_path path)
3041  * object MeCab_Path MeCab_Path::getRNext(void)
3042  *
3043  * Get the rnext path.
3044  *
3045  * @param	resource mecab_path	$path	The path of the source string.
3046  * @return	resource mecab_path	The rnext path.
3047  *								If the given path is the first one, returns FALSE.
3048  */
PHP_FUNCTION(mecab_path_rnext)3049 static PHP_FUNCTION(mecab_path_rnext)
3050 {
3051 	php_mecab_path_get_sibling_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PATH_RNEXT);
3052 }
3053 /* }}} mecab_path_rnext */
3054 
3055 /* {{{ proto resource mecab_path mecab_path_lnext(resource mecab_path path) */
3056 /**
3057  * resource mecab_path mecab_path_lnext(resource mecab_path path)
3058  * object MeCab_Path MeCab_Path::getLNext(void)
3059  *
3060  * Get the lnext path.
3061  *
3062  * @param	resource mecab_path	$path	The path of the source string.
3063  * @return	resource mecab_path	The lnext path.
3064  *								If the given path is the last one, returns FALSE.
3065  */
PHP_FUNCTION(mecab_path_lnext)3066 static PHP_FUNCTION(mecab_path_lnext)
3067 {
3068 	php_mecab_path_get_sibling_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PATH_LNEXT);
3069 }
3070 /* }}} mecab_path_lnext */
3071 
3072 /* {{{ proto resource mecab_node mecab_path_rnode(resource mecab_path path) */
3073 /**
3074  * resource mecab_node mecab_path_rnode(resource mecab_path path)
3075  * object MeCab_Node MeCab_Path::getRNode(void)
3076  *
3077  * Get the rnode.
3078  *
3079  * @param	resource mecab_path	$path	The path of the source string.
3080  * @return	resource mecab_node	The next path which has same end point as the given path.
3081  *								If there is no `rnode' path, returns false.
3082  */
PHP_FUNCTION(mecab_path_rnode)3083 static PHP_FUNCTION(mecab_path_rnode)
3084 {
3085 	php_mecab_path_get_node_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PATH_RNODE);
3086 }
3087 /* }}} mecab_path_rnode */
3088 
3089 /* {{{ proto resource mecab_node mecab_path_lnode(resource mecab_path path) */
3090 /**
3091  * resource mecab_node mecab_path_lnode(resource mecab_path path)
3092  * object MeCab_Node MeCab_Path::getLNode(void)
3093  *
3094  * Get the lnode.
3095  *
3096  * @param	resource mecab_path	$path	The path of the source string.
3097  * @return	resource mecab_node	The next path which has same beggining point as the given one.
3098  *								If there is no `lnode' path, returns false.
3099  */
PHP_FUNCTION(mecab_path_lnode)3100 static PHP_FUNCTION(mecab_path_lnode)
3101 {
3102 	php_mecab_path_get_node_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PATH_LNODE);
3103 }
3104 /* }}} mecab_path_lnode */
3105 
3106 /* {{{ proto double mecab_path_prob(resource mecab_path path) */
3107 /**
3108  * double mecab_path_prob(resource mecab_path path)
3109  * double MeCab_Path::getProb(void)
3110  *
3111  * Get the marginal probability.
3112  *
3113  * @param	resource mecab_path	$path	The path of the source string.
3114  * @return	double	The marginal probability of the path.
3115  */
PHP_FUNCTION(mecab_path_prob)3116 static PHP_FUNCTION(mecab_path_prob)
3117 {
3118 	PHP_MECAB_PATH_RETURN_PROPERTY(DOUBLE, (double)(path->prob));
3119 }
3120 /* }}} mecab_path_prob */
3121 
3122 /* {{{ proto int mecab_path_cost(resource mecab_path path) */
3123 /**
3124  * int mecab_path_cost(resource mecab_path path)
3125  * int MeCab_Path::getCost(void)
3126  *
3127  * Get the cumulative cost.
3128  *
3129  * @param	resource mecab_path	$path	The path of the source string.
3130  * @return	int	The cumulative cost of the path.
3131  */
PHP_FUNCTION(mecab_path_cost)3132 static PHP_FUNCTION(mecab_path_cost)
3133 {
3134 	PHP_MECAB_PATH_RETURN_PROPERTY(LONG, (long)(path->cost));
3135 }
3136 /* }}} mecab_node_cost */
3137 
3138 /* }}} Functions */
3139 
3140 /* {{{ methods */
3141 
3142 /* {{{ methods of class MeCab_Node*/
3143 
3144 /* {{{ proto object MeCab_Node __construct(void) */
3145 /**
3146  * object MeCab_Node MeCab_Node::__construct(void)
3147  *
3148  * Create MeCab_Node object.
3149  *
3150  * @access	private
3151  * @igore
3152  */
PHP_METHOD(MeCab_Node,__construct)3153 static PHP_METHOD(MeCab_Node, __construct)
3154 {
3155 	return;
3156 }
3157 /* }}} MeCab_Node::__construct */
3158 
3159 /* {{{ proto mixed MeCab_Node::__get(string name) */
3160 /**
3161  * mixed MeCab_Node::__get(string name)
3162  *
3163  * [Overloading implementation]
3164  * A magick getter.
3165  *
3166  * @param	string	$name	The name of property.
3167  * @return	mixed	The value of the property.
3168  *					If there is not a named property, causes E_NOTICE error and returns false.
3169  * @access	public
3170  * @ignore
3171  */
PHP_METHOD(MeCab_Node,__get)3172 static PHP_METHOD(MeCab_Node, __get)
3173 {
3174 	/* declaration of the resources */
3175 	zval *object = getThis();
3176 	php_mecab_node *xnode = NULL;
3177 	const mecab_node_t *node = NULL;
3178 
3179 	/* declaration of the arguments */
3180 	char *name = NULL;
3181 	int name_len = 0;
3182 
3183 	/* parse the arguments */
3184 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
3185 		return;
3186 	} else {
3187 		php_mecab_node_object *intern;
3188 		PHP_MECAB_FETCH_OBJECT(intern, php_mecab_node_object *, object);
3189 		xnode = intern->ptr;
3190 		node = xnode->ptr;
3191 	}
3192 
3193 	/* check for given property name */
3194 	if (!strcmp(name, "prev")) {
3195 		php_mecab_node_get_sibling(return_value, object, xnode, NODE_PREV TSRMLS_CC);
3196 		return;
3197 	}
3198 	if (!strcmp(name, "next")) {
3199 		php_mecab_node_get_sibling(return_value, object, xnode, NODE_NEXT TSRMLS_CC);
3200 		return;
3201 	}
3202 	if (!strcmp(name, "enext")) {
3203 		php_mecab_node_get_sibling(return_value, object, xnode, NODE_ENEXT TSRMLS_CC);
3204 		return;
3205 	}
3206 	if (!strcmp(name, "bnext")) {
3207 		php_mecab_node_get_sibling(return_value, object, xnode, NODE_BNEXT TSRMLS_CC);
3208 		return;
3209 	}
3210 	if (!strcmp(name, "rpath")) {
3211 		php_mecab_node_get_path(return_value, object, xnode, NODE_RPATH TSRMLS_CC);
3212 		return;
3213 	}
3214 	if (!strcmp(name, "lpath")) {
3215 		php_mecab_node_get_path(return_value, object, xnode, NODE_LPATH TSRMLS_CC);
3216 		return;
3217 	}
3218 	if (!strcmp(name, "surface"))   RETURN_STRINGL((char *)node->surface, (int)node->length, 1);
3219 	if (!strcmp(name, "feature"))   RETURN_STRING((char *)node->feature, 1);
3220 	if (!strcmp(name, "id"))        RETURN_LONG((long)node->id);
3221 	if (!strcmp(name, "length"))    RETURN_LONG((long)node->length);
3222 	if (!strcmp(name, "rlength"))   RETURN_LONG((long)node->rlength);
3223 	if (!strcmp(name, "rcAttr"))    RETURN_LONG((long)node->rcAttr);
3224 	if (!strcmp(name, "lcAttr"))    RETURN_LONG((long)node->lcAttr);
3225 	if (!strcmp(name, "posid"))     RETURN_LONG((long)node->posid);
3226 	if (!strcmp(name, "char_type")) RETURN_LONG((long)node->char_type);
3227 	if (!strcmp(name, "stat"))      RETURN_LONG((long)node->stat);
3228 	if (!strcmp(name, "isbest"))    RETURN_BOOL((long)node->isbest);
3229 	if (!strcmp(name, "alpha"))     RETURN_DOUBLE((double)node->alpha);
3230 	if (!strcmp(name, "beta"))      RETURN_DOUBLE((double)node->beta);
3231 	if (!strcmp(name, "prob"))      RETURN_DOUBLE((double)node->prob);
3232 	if (!strcmp(name, "wcost"))     RETURN_LONG((long)node->wcost);
3233 	if (!strcmp(name, "cost"))      RETURN_LONG((long)node->cost);
3234 
3235 	/* when going to fetch undefined property */
3236 	php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Undefined property (%s)", name);
3237 	RETURN_NULL();
3238 }
3239 /* }}} MeCab_Node::__get */
3240 
3241 /* {{{ proto bool MeCab_Node::__isset(string name) */
3242 /**
3243  * bool MeCab_Node::__isset(string name)
3244  *
3245  * [Overloading implementation]
3246  * Determine whether there is a named property.
3247  *
3248  * @param	string	$name	The name of property.
3249  * @return	bool	True if there is a named property, otherwise returns false.
3250  * @access	public
3251  * @ignore
3252  */
PHP_METHOD(MeCab_Node,__isset)3253 static PHP_METHOD(MeCab_Node, __isset)
3254 {
3255 	/* declaration of the resources */
3256 	zval *object = getThis();
3257 	php_mecab_node *xnode = NULL;
3258 	const mecab_node_t *node = NULL;
3259 
3260 	/* declaration of the arguments */
3261 	char *name = NULL;
3262 	int name_len = 0;
3263 
3264 	/* parse the arguments */
3265 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
3266 		return;
3267 	} else {
3268 		php_mecab_node_object *intern;
3269 		PHP_MECAB_FETCH_OBJECT(intern, php_mecab_node_object *, object);
3270 		xnode = intern->ptr;
3271 		node = xnode->ptr;
3272 	}
3273 
3274 	/* check for given property name */
3275 	if ((!strcmp(name, "prev") && node->prev != NULL) ||
3276 		(!strcmp(name, "next") && node->next != NULL) ||
3277 		(!strcmp(name, "enext") && node->enext != NULL) ||
3278 		(!strcmp(name, "bnext") && node->bnext != NULL) ||
3279 		(!strcmp(name, "rpath") && node->rpath != NULL) ||
3280 		(!strcmp(name, "lpath") && node->lpath != NULL) ||
3281 		!strcmp(name, "surface") ||
3282 		!strcmp(name, "feature") ||
3283 		!strcmp(name, "id") ||
3284 		!strcmp(name, "length") ||
3285 		!strcmp(name, "rlength") ||
3286 		!strcmp(name, "rcAttr") ||
3287 		!strcmp(name, "lcAttr") ||
3288 		!strcmp(name, "posid") ||
3289 		!strcmp(name, "char_type") ||
3290 		!strcmp(name, "stat") ||
3291 		!strcmp(name, "isbest") ||
3292 		!strcmp(name, "sentence_length") ||
3293 		!strcmp(name, "alpha") ||
3294 		!strcmp(name, "beta") ||
3295 		!strcmp(name, "prob") ||
3296 		!strcmp(name, "wcost") ||
3297 		!strcmp(name, "cost"))
3298 	{
3299 		RETURN_TRUE;
3300 	}
3301 	RETURN_FALSE;
3302 }
3303 /* }}} MeCab_Node::__isset */
3304 
3305 /* {{{ proto object MeCab_NodeIterator MeCab_Node::getIterator(void) */
3306 /**
3307  * object MeCab_NodeIterator MeCab_Node::getIterator(void)
3308  *
3309  * [IteratorAggregate implementation]
3310  * Return the iterator object.
3311  *
3312  * @return	object MeCab_NodeIterator
3313  * @access	public
3314  * @ignore
3315  */
PHP_METHOD(MeCab_Node,getIterator)3316 static PHP_METHOD(MeCab_Node, getIterator)
3317 {
3318 	php_mecab_node_object *intern;
3319 	php_mecab_node *xnode;
3320 	const mecab_node_t *node;
3321 	php_mecab_node_object *newobj;
3322 	php_mecab_node *newnode;
3323 
3324 	intern = (php_mecab_node_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
3325 	xnode = intern->ptr;
3326 	node = xnode->ptr;
3327 
3328 	if (node == NULL) {
3329 		RETURN_NULL();
3330 	}
3331 
3332 	object_init_ex(return_value, ce_MeCab_NodeIterator);
3333 	PHP_MECAB_FETCH_OBJECT(newobj, php_mecab_node_object *, return_value);
3334 	newobj->root = node;
3335 	newobj->mode = intern->mode;
3336 	newnode = newobj->ptr;
3337 	newnode->ptr = node;
3338 	php_mecab_node_set_tagger(newnode, xnode->tagger TSRMLS_CC);
3339 }
3340 /* }}} MeCab_Node::getIterator */
3341 
3342 /* {{{ proto void MeCab_Node::setTraverse(int tranverse) */
3343 /**
3344  * void MeCab_Node::setTraverse(int tranverse)
3345  *
3346  * Set the traverse mode.
3347  *
3348  * @param	int	$traverse	The traverse mode.
3349  * @return	void
3350  * @throws	InvalidArgumentException
3351  * @access	public
3352  */
PHP_METHOD(MeCab_Node,setTraverse)3353 static PHP_METHOD(MeCab_Node, setTraverse)
3354 {
3355 	php_mecab_node_object *intern;
3356 	long traverse = 0;
3357 
3358 #if PHP_VERSION_ID >= 50300
3359 	zend_error_handling error_handling;
3360 
3361 	zend_replace_error_handling(EH_THROW, ext_ce_InvalidArgumentException, &error_handling TSRMLS_CC);
3362 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &traverse) == FAILURE) {
3363 		zend_restore_error_handling(&error_handling TSRMLS_CC);
3364 		return;
3365 	}
3366 	zend_restore_error_handling(&error_handling TSRMLS_CC);
3367 #else
3368 	php_set_error_handling(EH_THROW, ext_ce_InvalidArgumentException TSRMLS_CC);
3369 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &traverse) == FAILURE) {
3370 		php_std_error_handling();
3371 		return;
3372 	}
3373 	php_std_error_handling();
3374 #endif
3375 
3376 	intern = (php_mecab_node_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
3377 
3378 	if (traverse == (long)TRAVERSE_NEXT ||
3379 		traverse == (long)TRAVERSE_ENEXT ||
3380 		traverse == (long)TRAVERSE_BNEXT)
3381 	{
3382 		intern->mode = (php_mecab_traverse_mode)traverse;
3383 	} else {
3384 		zend_throw_exception(ext_ce_InvalidArgumentException,
3385 				"Invalid traverse mdoe given", 0 TSRMLS_CC);
3386 	}
3387 }
3388 /* }}} MeCab_Node::setTraverse */
3389 
3390 /* }}} methods of class MeCab_Node */
3391 
3392 /* {{{ methods of class MeCab_NodeIterator*/
3393 
3394 /* {{{ proto object MeCab_NodeIterator __construct(void) */
3395 /**
3396  * object MeCab_Path MeCab_NodeIterator::__construct(void)
3397  *
3398  * Create MeCab_NodeIterator object.
3399  *
3400  * @access	private
3401  * @igore
3402  */
PHP_METHOD(MeCab_NodeIterator,__construct)3403 static PHP_METHOD(MeCab_NodeIterator, __construct)
3404 {
3405 	return;
3406 }
3407 /* }}} MeCab_NodeIterator::__construct */
3408 
3409 /* {{{ object MeCab_Node MeCab_NodeIterator::current(void) */
3410 /**
3411  * object MeCab_Node MeCab_NodeIterator::current(void)
3412  *
3413  * [Iterator implementation]
3414  * Return the current element.
3415  *
3416  * @access	public
3417  * @igore
3418  */
PHP_METHOD(MeCab_NodeIterator,current)3419 static PHP_METHOD(MeCab_NodeIterator, current)
3420 {
3421 	php_mecab_node_object *intern;
3422 	php_mecab_node *xnode;
3423 	const mecab_node_t *node;
3424 	php_mecab_node_object *newobj;
3425 	php_mecab_node *newnode;
3426 
3427 	if (ZEND_NUM_ARGS() != 0) {
3428 		WRONG_PARAM_COUNT;
3429 	}
3430 	intern = (php_mecab_node_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
3431 	xnode = intern->ptr;
3432 	node = xnode->ptr;
3433 
3434 	if (node == NULL) {
3435 		RETURN_NULL();
3436 	}
3437 
3438 	object_init_ex(return_value, ce_MeCab_Node);
3439 	PHP_MECAB_FETCH_OBJECT(newobj, php_mecab_node_object *, return_value);
3440 	newobj->mode = intern->mode;
3441 	newnode = newobj->ptr;
3442 	newnode->ptr = node;
3443 	php_mecab_node_set_tagger(newnode, xnode->tagger TSRMLS_CC);
3444 }
3445 /* }}} MeCab_NodeIterator::current */
3446 
3447 /* {{{ proto int MeCab_NodeIterator::key(void) */
3448 /**
3449  * int MeCab_Node::key(void)
3450  *
3451  * [Iterator implementation]
3452  * Return the key of the current element.
3453  *
3454  * @return	int	The cumulative cost of the node.
3455  * @access	public
3456  * @igore
3457  */
PHP_METHOD(MeCab_NodeIterator,key)3458 static PHP_METHOD(MeCab_NodeIterator, key)
3459 {
3460 	php_mecab_node_object *intern;
3461 	php_mecab_node *xnode;
3462 	const mecab_node_t *node;
3463 
3464 	if (ZEND_NUM_ARGS() != 0) {
3465 		WRONG_PARAM_COUNT;
3466 	}
3467 	intern = (php_mecab_node_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
3468 	xnode = intern->ptr;
3469 	node = xnode->ptr;
3470 
3471 	if (node == NULL) {
3472 		RETURN_NULL();
3473 	}
3474 
3475 	RETURN_LONG((long)node->id);
3476 }
3477 /* }}} MeCab_NodeIterator::key */
3478 
3479 /* {{{ proto void MeCab_NodeIterator::next(void) */
3480 /**
3481  * void MeCab_NodeIterator::next(void)
3482  *
3483  * [Iterator implementation]
3484  * Set the node pointer to the next.
3485  *
3486  * @return	void
3487  * @access	public
3488  * @igore
3489  */
PHP_METHOD(MeCab_NodeIterator,next)3490 static PHP_METHOD(MeCab_NodeIterator, next)
3491 {
3492 	php_mecab_node_object *intern;
3493 	php_mecab_node *xnode;
3494 	const mecab_node_t *node;
3495 
3496 	if (ZEND_NUM_ARGS() != 0) {
3497 		WRONG_PARAM_COUNT;
3498 	}
3499 	intern = (php_mecab_node_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
3500 	xnode = intern->ptr;
3501 	node = xnode->ptr;
3502 
3503 	if (node == NULL) {
3504 		return;
3505 	}
3506 
3507 	switch (intern->mode) {
3508 	  case TRAVERSE_NEXT:
3509 		xnode->ptr = node->next;
3510 		break;
3511 	  case TRAVERSE_ENEXT:
3512 		xnode->ptr = node->enext;
3513 		break;
3514 	  case TRAVERSE_BNEXT:
3515 		xnode->ptr = node->bnext;
3516 		break;
3517 	  default:
3518 		xnode->ptr = NULL;
3519 	}
3520 }
3521 /* }}} MeCab_NodeIterator::next */
3522 
3523 /* {{{ proto void MeCab_NodeIterator::rewind(void) */
3524 /**
3525  * void MeCab_NodeIterator::rewind(void)
3526  *
3527  * [Iterator implementation]
3528  * Set the node pointer to the beginning.
3529  *
3530  * @return	void
3531  * @access	public
3532  * @igore
3533  */
PHP_METHOD(MeCab_NodeIterator,rewind)3534 static PHP_METHOD(MeCab_NodeIterator, rewind)
3535 {
3536 	php_mecab_node_object *intern;
3537 	php_mecab_node *xnode;
3538 
3539 	if (ZEND_NUM_ARGS() != 0) {
3540 		WRONG_PARAM_COUNT;
3541 	}
3542 	intern = (php_mecab_node_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
3543 	xnode = intern->ptr;
3544 	xnode->ptr = intern->root;
3545 }
3546 /* }}} MeCab_NodeIterator::rewind */
3547 
3548 /* {{{ proto bool MeCab_NodeIterator::valid(void) */
3549 /**
3550  * bool MeCab_NodeIterator::valid(void)
3551  *
3552  * [Iterator implementation]
3553  * Check if there is a current element after calls to rewind() or next().
3554  *
3555  * @return	bool	True if there is an element after the current element, otherwise returns false.
3556  * @access	public
3557  * @igore
3558  */
PHP_METHOD(MeCab_NodeIterator,valid)3559 static PHP_METHOD(MeCab_NodeIterator, valid)
3560 {
3561 	php_mecab_node_object *intern;
3562 	php_mecab_node *xnode;
3563 	const mecab_node_t *node;
3564 
3565 	if (ZEND_NUM_ARGS() != 0) {
3566 		WRONG_PARAM_COUNT;
3567 	}
3568 	intern = (php_mecab_node_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
3569 	xnode = intern->ptr;
3570 	node = xnode->ptr;
3571 
3572 	RETURN_BOOL(node != NULL);
3573 }
3574 /* }}} MeCab_NodeIterator::valid */
3575 
3576 /* }}} methods of class MeCab_NodeIterator */
3577 
3578 /* {{{ methods of class MeCab_Path*/
3579 
3580 /* {{{ proto object MeCab_Path __construct(void) */
3581 /**
3582  * object MeCab_Path MeCab_Path::__construct(void)
3583  *
3584  * Create MeCab_Path object.
3585  *
3586  * @access	private
3587  * @igore
3588  */
PHP_METHOD(MeCab_Path,__construct)3589 static PHP_METHOD(MeCab_Path, __construct)
3590 {
3591 	return;
3592 }
3593 /* }}} MeCab_Path::__construct */
3594 
3595 /* {{{ proto mixed MeCab_Path::__get(string name) */
3596 /**
3597  * mixed MeCab_Path::__get(string name)
3598  *
3599  * [Overloading implementation]
3600  * A magick getter.
3601  *
3602  * @param	string	$name	The name of property.
3603  * @return	mixed	The value of the property.
3604  *					If there is not a named property, causes E_NOTICE error and returns false.
3605  * @access	public
3606  * @ignore
3607  */
PHP_METHOD(MeCab_Path,__get)3608 static PHP_METHOD(MeCab_Path, __get)
3609 {
3610 	/* declaration of the resources */
3611 	zval *object = getThis();
3612 	php_mecab_path *xpath = NULL;
3613 	const mecab_path_t *path = NULL;
3614 
3615 	/* declaration of the arguments */
3616 	char *name = NULL;
3617 	int name_len = 0;
3618 
3619 	/* parse the arguments */
3620 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
3621 		return;
3622 	} else {
3623 		php_mecab_path_object *intern;
3624 		PHP_MECAB_FETCH_OBJECT(intern, php_mecab_path_object *, object);
3625 		xpath = intern->ptr;
3626 		path = xpath->ptr;
3627 	}
3628 
3629 	/* check for given property name */
3630 	if (!strcmp(name, "rnext")) {
3631 		php_mecab_path_get_sibling(return_value, object, xpath, PATH_RNEXT TSRMLS_CC);
3632 		return;
3633 	}
3634 	if (!strcmp(name, "lnext")) {
3635 		php_mecab_path_get_sibling(return_value, object, xpath, PATH_LNEXT TSRMLS_CC);
3636 		return;
3637 	}
3638 	if (!strcmp(name, "rnode")) {
3639 		php_mecab_path_get_node(return_value, object, xpath, PATH_RNODE TSRMLS_CC);
3640 		return;
3641 	}
3642 	if (!strcmp(name, "lnode")) {
3643 		php_mecab_path_get_node(return_value, object, xpath, PATH_LNODE TSRMLS_CC);
3644 		return;
3645 	}
3646 	if (!strcmp(name, "prob")) RETURN_DOUBLE((double)(path->prob));
3647 	if (!strcmp(name, "cost")) RETURN_LONG((long)(path->cost));
3648 
3649 	/* when going to fetch undefined property */
3650 	php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Undefined property (%s)", name);
3651 	RETURN_NULL();
3652 }
3653 /* }}} MeCab_Path::__get */
3654 
3655 /* {{{ proto boolMeCab_Path:: __isset(string name) */
3656 /**
3657  * bool MeCab_Path::__isset(string name)
3658  *
3659  * [Overloading implementation]
3660  * Determine whether there is a named property.
3661  *
3662  * @param	string	$name	The name of property.
3663  * @return	bool	True if there is a named property, otherwise returns false.
3664  * @access	public
3665  * @ignore
3666  */
PHP_METHOD(MeCab_Path,__isset)3667 static PHP_METHOD(MeCab_Path, __isset)
3668 {
3669 	/* declaration of the resources */
3670 	zval *object = getThis();
3671 	php_mecab_path *xpath = NULL;
3672 	const mecab_path_t *path = NULL;
3673 
3674 	/* declaration of the arguments */
3675 	char *name = NULL;
3676 	int name_len = 0;
3677 
3678 	/* parse the arguments */
3679 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
3680 		return;
3681 	} else {
3682 		php_mecab_path_object *intern;
3683 		PHP_MECAB_FETCH_OBJECT(intern, php_mecab_path_object *, object);
3684 		xpath = intern->ptr;
3685 		path = xpath->ptr;
3686 	}
3687 
3688 	/* check for given property name */
3689 	if ((!strcmp(name, "rnext") && path->rnext != NULL) ||
3690 		(!strcmp(name, "lnext") && path->lnext != NULL) ||
3691 		(!strcmp(name, "rnode") && path->rnode != NULL) ||
3692 		(!strcmp(name, "lnode") && path->lnode != NULL) ||
3693 		!strcmp(name, "prob") ||
3694 		!strcmp(name, "cost"))
3695 	{
3696 		RETURN_TRUE;
3697 	}
3698 	RETURN_FALSE;
3699 }
3700 /* }}} MeCab_Path::__isset */
3701 
3702 /* }}} methods of class MeCab_Path */
3703 
3704 /* }}} methods */
3705 
3706 /*
3707  * Local variables:
3708  * tab-width: 4
3709  * c-basic-offset: 4
3710  * End:
3711  * vim600: noet sw=4 ts=4 fdm=marker
3712  * vim<600: noet sw=4 ts=4
3713  */
3714