no timestamp
[m6w6/ext-raphf] / php_raphf.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: raphf |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2013, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include "php.h"
18 #include "php_ini.h"
19 #include "ext/standard/info.h"
20 #include "php_raphf.h"
21
22 struct php_persistent_handle_globals {
23 ulong limit;
24 HashTable hash;
25 };
26
27 ZEND_BEGIN_MODULE_GLOBALS(raphf)
28 struct php_persistent_handle_globals persistent_handle;
29 ZEND_END_MODULE_GLOBALS(raphf)
30
31 #ifdef ZTS
32 # define PHP_RAPHF_G ((zend_raphf_globals *) \
33 (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(raphf_globals_id)])
34 #else
35 # define PHP_RAPHF_G (&raphf_globals)
36 #endif
37
38 ZEND_DECLARE_MODULE_GLOBALS(raphf)
39
40 typedef int STATUS;
41
42 #ifndef PHP_RAPHF_DEBUG_PHANDLES
43 # define PHP_RAPHF_DEBUG_PHANDLES 0
44 #endif
45 #if PHP_RAPHF_DEBUG_PHANDLES
46 # undef inline
47 # define inline
48 #endif
49
50 php_resource_factory_t *php_resource_factory_init(php_resource_factory_t *f,
51 php_resource_factory_ops_t *fops, void *data, void (*dtor)(void *data))
52 {
53 if (!f) {
54 f = emalloc(sizeof(*f));
55 }
56 memset(f, 0, sizeof(*f));
57
58 memcpy(&f->fops, fops, sizeof(*fops));
59
60 f->data = data;
61 f->dtor = dtor;
62
63 f->refcount = 1;
64
65 return f;
66 }
67
68 unsigned php_resource_factory_addref(php_resource_factory_t *rf)
69 {
70 return ++rf->refcount;
71 }
72
73 void php_resource_factory_dtor(php_resource_factory_t *f)
74 {
75 --f->refcount;
76
77 if (!f->refcount) {
78 if (f->dtor) {
79 f->dtor(f->data);
80 }
81 }
82 }
83
84 void php_resource_factory_free(php_resource_factory_t **f)
85 {
86 if (*f) {
87 php_resource_factory_dtor(*f);
88 if (!(*f)->refcount) {
89 efree(*f);
90 *f = NULL;
91 }
92 }
93 }
94
95 void *php_resource_factory_handle_ctor(php_resource_factory_t *f,
96 void *init_arg TSRMLS_DC)
97 {
98 if (f->fops.ctor) {
99 return f->fops.ctor(f->data, init_arg TSRMLS_CC);
100 }
101 return NULL;
102 }
103
104 void *php_resource_factory_handle_copy(php_resource_factory_t *f,
105 void *handle TSRMLS_DC)
106 {
107 if (f->fops.copy) {
108 return f->fops.copy(f->data, handle TSRMLS_CC);
109 }
110 return NULL;
111 }
112
113 void php_resource_factory_handle_dtor(php_resource_factory_t *f,
114 void *handle TSRMLS_DC)
115 {
116 if (f->fops.dtor) {
117 f->fops.dtor(f->data, handle TSRMLS_CC);
118 }
119 }
120
121 static inline php_persistent_handle_list_t *php_persistent_handle_list_init(
122 php_persistent_handle_list_t *list)
123 {
124 int free_list;
125
126 if ((free_list = !list)) {
127 list = pemalloc(sizeof(php_persistent_handle_list_t), 1);
128 }
129
130 list->used = 0;
131
132 if (SUCCESS != zend_hash_init(&list->free, 0, NULL, NULL, 1)) {
133 if (free_list) {
134 pefree(list, 1);
135 }
136 list = NULL;
137 }
138
139 return list;
140 }
141
142 static int php_persistent_handle_apply_stat(void *p TSRMLS_DC, int argc,
143 va_list argv, zend_hash_key *key)
144 {
145 php_persistent_handle_list_t **list = p;
146 zval *zsubentry, *zentry = va_arg(argv, zval *);
147
148 MAKE_STD_ZVAL(zsubentry);
149 array_init(zsubentry);
150 add_assoc_long_ex(zsubentry, ZEND_STRS("used"), (*list)->used);
151 add_assoc_long_ex(zsubentry, ZEND_STRS("free"),
152 zend_hash_num_elements(&(*list)->free));
153 add_assoc_zval_ex(zentry, key->arKey, key->nKeyLength, zsubentry);
154
155 return ZEND_HASH_APPLY_KEEP;
156 }
157
158 static int php_persistent_handle_apply_statall(void *p TSRMLS_DC, int argc,
159 va_list argv, zend_hash_key *key)
160 {
161 php_persistent_handle_provider_t *provider = p;
162 HashTable *ht = va_arg(argv, HashTable *);
163 zval *zentry;
164
165 MAKE_STD_ZVAL(zentry);
166 array_init(zentry);
167
168 zend_hash_apply_with_arguments(&provider->list.free TSRMLS_CC,
169 php_persistent_handle_apply_stat, 1, zentry);
170 zend_symtable_update(ht, key->arKey, key->nKeyLength, &zentry,
171 sizeof(zval *), NULL);
172
173 return ZEND_HASH_APPLY_KEEP;
174 }
175
176 static int php_persistent_handle_apply_cleanup_ex(void *pp, void *arg TSRMLS_DC)
177 {
178 php_resource_factory_t *rf = arg;
179 void **handle = pp;
180
181 #if PHP_RAPHF_DEBUG_PHANDLES
182 fprintf(stderr, "DESTROY: %p\n", *handle);
183 #endif
184 php_resource_factory_handle_dtor(rf, *handle TSRMLS_CC);
185 return ZEND_HASH_APPLY_REMOVE;
186 }
187
188 static int php_persistent_handle_apply_cleanup(void *pp, void *arg TSRMLS_DC)
189 {
190 php_resource_factory_t *rf = arg;
191 php_persistent_handle_list_t **listp = pp;
192
193 zend_hash_apply_with_argument(&(*listp)->free,
194 php_persistent_handle_apply_cleanup_ex, rf TSRMLS_CC);
195 if ((*listp)->used) {
196 return ZEND_HASH_APPLY_KEEP;
197 }
198 zend_hash_destroy(&(*listp)->free);
199 #if PHP_RAPHF_DEBUG_PHANDLES
200 fprintf(stderr, "LSTFREE: %p\n", *listp);
201 #endif
202 pefree(*listp, 1);
203 *listp = NULL;
204 return ZEND_HASH_APPLY_REMOVE;
205 }
206
207 static inline void php_persistent_handle_list_dtor(
208 php_persistent_handle_list_t *list,
209 php_persistent_handle_provider_t *provider TSRMLS_DC)
210 {
211 #if PHP_RAPHF_DEBUG_PHANDLES
212 fprintf(stderr, "LSTDTOR: %p\n", list);
213 #endif
214 zend_hash_apply_with_argument(&list->free,
215 php_persistent_handle_apply_cleanup_ex, &provider->rf TSRMLS_CC);
216 zend_hash_destroy(&list->free);
217 }
218
219 static inline void php_persistent_handle_list_free(
220 php_persistent_handle_list_t **list,
221 php_persistent_handle_provider_t *provider TSRMLS_DC)
222 {
223 php_persistent_handle_list_dtor(*list, provider TSRMLS_CC);
224 #if PHP_RAPHF_DEBUG_PHANDLES
225 fprintf(stderr, "LSTFREE: %p\n", *list);
226 #endif
227 pefree(*list, 1);
228 *list = NULL;
229 }
230
231 static int php_persistent_handle_list_apply_dtor(void *listp,
232 void *provider TSRMLS_DC)
233 {
234 php_persistent_handle_list_free(listp, provider TSRMLS_CC);
235 return ZEND_HASH_APPLY_REMOVE;
236 }
237
238 static inline php_persistent_handle_list_t *php_persistent_handle_list_find(
239 php_persistent_handle_provider_t *provider, const char *ident_str,
240 size_t ident_len TSRMLS_DC)
241 {
242 php_persistent_handle_list_t **list, *new_list;
243 STATUS rv = zend_symtable_find(&provider->list.free, ident_str,
244 ident_len + 1, (void *) &list);
245
246 if (SUCCESS == rv) {
247 #if PHP_RAPHF_DEBUG_PHANDLES
248 fprintf(stderr, "LSTFIND: %p\n", *list);
249 #endif
250 return *list;
251 }
252
253 if ((new_list = php_persistent_handle_list_init(NULL))) {
254 rv = zend_symtable_update(&provider->list.free, ident_str, ident_len+1,
255 (void *) &new_list, sizeof(php_persistent_handle_list_t *),
256 (void *) &list);
257 if (SUCCESS == rv) {
258 #if PHP_RAPHF_DEBUG_PHANDLES
259 fprintf(stderr, "LSTFIND: %p (new)\n", *list);
260 #endif
261 return *list;
262 }
263 php_persistent_handle_list_free(&new_list, provider TSRMLS_CC);
264 }
265
266 return NULL;
267 }
268
269 static int php_persistent_handle_apply_cleanup_all(void *p TSRMLS_DC, int argc,
270 va_list argv, zend_hash_key *key)
271 {
272 php_persistent_handle_provider_t *provider = p;
273 const char *ident_str = va_arg(argv, const char *);
274 size_t ident_len = va_arg(argv, size_t);
275 php_persistent_handle_list_t *list;
276
277 if (ident_str && ident_len) {
278 if ((list = php_persistent_handle_list_find(provider, ident_str,
279 ident_len TSRMLS_CC))) {
280 zend_hash_apply_with_argument(&list->free,
281 php_persistent_handle_apply_cleanup_ex,
282 &provider->rf TSRMLS_CC);
283 }
284 } else {
285 zend_hash_apply_with_argument(&provider->list.free,
286 php_persistent_handle_apply_cleanup, &provider->rf TSRMLS_CC);
287 }
288
289 return ZEND_HASH_APPLY_KEEP;
290 }
291
292 static void php_persistent_handle_hash_dtor(void *p)
293 {
294 php_persistent_handle_provider_t *provider;
295 TSRMLS_FETCH();
296
297 provider = (php_persistent_handle_provider_t *) p;
298 zend_hash_apply_with_argument(&provider->list.free,
299 php_persistent_handle_list_apply_dtor, provider TSRMLS_CC);
300 zend_hash_destroy(&provider->list.free);
301 php_resource_factory_dtor(&provider->rf);
302 }
303
304 PHP_RAPHF_API STATUS php_persistent_handle_provide(const char *name_str,
305 size_t name_len, php_resource_factory_ops_t *fops, void *data,
306 void (*dtor)(void *) TSRMLS_DC)
307 {
308 STATUS status = FAILURE;
309 php_persistent_handle_provider_t provider;
310
311 if (php_persistent_handle_list_init(&provider.list)) {
312 if (php_resource_factory_init(&provider.rf, fops, data, dtor)) {
313 #if PHP_RAPHF_DEBUG_PHANDLES
314 fprintf(stderr, "PROVIDE: %p %s\n", PHP_RAPHF_G, name_str);
315 #endif
316
317 status = zend_symtable_update(&PHP_RAPHF_G->persistent_handle.hash,
318 name_str, name_len+1, (void *) &provider,
319 sizeof(php_persistent_handle_provider_t), NULL);
320 if (SUCCESS != status) {
321 php_resource_factory_dtor(&provider.rf);
322 }
323 }
324 }
325
326 return status;
327 }
328
329 php_persistent_handle_factory_t *php_persistent_handle_concede(
330 php_persistent_handle_factory_t *a, const char *name_str,
331 size_t name_len, const char *ident_str, size_t ident_len,
332 php_persistent_handle_wakeup_t wakeup,
333 php_persistent_handle_retire_t retire TSRMLS_DC)
334 {
335 STATUS status = FAILURE;
336 php_persistent_handle_factory_t *free_a = NULL;
337
338 if (!a) {
339 free_a = a = emalloc(sizeof(*a));
340 }
341 memset(a, 0, sizeof(*a));
342
343 status = zend_symtable_find(&PHP_RAPHF_G->persistent_handle.hash, name_str,
344 name_len+1, (void *) &a->provider);
345
346 if (SUCCESS == status) {
347 a->ident.str = estrndup(ident_str, ident_len);
348 a->ident.len = ident_len;
349
350 a->wakeup = wakeup;
351 a->retire = retire;
352
353 if (free_a) {
354 a->free_on_abandon = 1;
355 }
356 } else {
357 if (free_a) {
358 efree(free_a);
359 }
360 a = NULL;
361 }
362
363 #if PHP_RAPHF_DEBUG_PHANDLES
364 fprintf(stderr, "CONCEDE: %p %p (%s) (%s)\n", PHP_RAPHF_G,
365 a ? a->provider : NULL, name_str, ident_str);
366 #endif
367
368 return a;
369 }
370
371 PHP_RAPHF_API void php_persistent_handle_abandon(
372 php_persistent_handle_factory_t *a)
373 {
374 zend_bool f = a->free_on_abandon;
375
376 #if PHP_RAPHF_DEBUG_PHANDLES
377 fprintf(stderr, "ABANDON: %p\n", a->provider);
378 #endif
379
380 STR_FREE(a->ident.str);
381 memset(a, 0, sizeof(*a));
382 if (f) {
383 efree(a);
384 }
385 }
386
387 void *php_persistent_handle_acquire(
388 php_persistent_handle_factory_t *a, void *init_arg TSRMLS_DC)
389 {
390 int key;
391 STATUS rv;
392 ulong index;
393 void **handle_ptr, *handle = NULL;
394 php_persistent_handle_list_t *list;
395
396 list = php_persistent_handle_list_find(a->provider, a->ident.str,
397 a->ident.len TSRMLS_CC);
398 if (list) {
399 zend_hash_internal_pointer_end(&list->free);
400 key = zend_hash_get_current_key(&list->free, NULL, &index, 0);
401 rv = zend_hash_get_current_data(&list->free, (void *) &handle_ptr);
402 if (HASH_KEY_NON_EXISTANT != key && SUCCESS == rv) {
403 handle = *handle_ptr;
404 if (a->wakeup) {
405 a->wakeup(a, &handle TSRMLS_CC);
406 }
407 zend_hash_index_del(&list->free, index);
408 } else {
409 handle = php_resource_factory_handle_ctor(&a->provider->rf,
410 init_arg TSRMLS_CC);
411 }
412 #if PHP_RAPHF_DEBUG_PHANDLES
413 fprintf(stderr, "CREATED: %p\n", *handle);
414 #endif
415 if (handle) {
416 ++a->provider->list.used;
417 ++list->used;
418 }
419 }
420
421 return handle;
422 }
423
424 void *php_persistent_handle_accrete(
425 php_persistent_handle_factory_t *a, void *handle TSRMLS_DC)
426 {
427 void *new_handle = NULL;
428 php_persistent_handle_list_t *list;
429
430 new_handle = php_resource_factory_handle_copy(&a->provider->rf,
431 handle TSRMLS_CC);
432 if (handle) {
433 list = php_persistent_handle_list_find(a->provider, a->ident.str,
434 a->ident.len TSRMLS_CC);
435 if (list) {
436 ++list->used;
437 }
438 ++a->provider->list.used;
439 }
440
441 return new_handle;
442 }
443
444 void php_persistent_handle_release(
445 php_persistent_handle_factory_t *a, void *handle TSRMLS_DC)
446 {
447 php_persistent_handle_list_t *list;
448
449 list = php_persistent_handle_list_find(a->provider, a->ident.str,
450 a->ident.len TSRMLS_CC);
451 if (list) {
452 if (a->provider->list.used >= PHP_RAPHF_G->persistent_handle.limit) {
453 #if PHP_RAPHF_DEBUG_PHANDLES
454 fprintf(stderr, "DESTROY: %p\n", *handle);
455 #endif
456 php_resource_factory_handle_dtor(&a->provider->rf,
457 handle TSRMLS_CC);
458 } else {
459 if (a->retire) {
460 a->retire(a, &handle TSRMLS_CC);
461 }
462 zend_hash_next_index_insert(&list->free, (void *) &handle,
463 sizeof(void *), NULL);
464 }
465
466 --a->provider->list.used;
467 --list->used;
468 }
469 }
470
471 void php_persistent_handle_cleanup(const char *name_str, size_t name_len,
472 const char *ident_str, size_t ident_len TSRMLS_DC)
473 {
474 php_persistent_handle_provider_t *provider;
475 php_persistent_handle_list_t *list;
476 STATUS rv;
477
478 if (name_str && name_len) {
479 rv = zend_symtable_find(&PHP_RAPHF_G->persistent_handle.hash, name_str,
480 name_len+1, (void *) &provider);
481
482 if (SUCCESS == rv) {
483 if (ident_str && ident_len) {
484 list = php_persistent_handle_list_find(provider, ident_str,
485 ident_len TSRMLS_CC);
486 if (list) {
487 zend_hash_apply_with_argument(&list->free,
488 php_persistent_handle_apply_cleanup_ex,
489 &provider->rf TSRMLS_CC);
490 }
491 } else {
492 zend_hash_apply_with_argument(&provider->list.free,
493 php_persistent_handle_apply_cleanup,
494 &provider->rf TSRMLS_CC);
495 }
496 }
497 } else {
498 zend_hash_apply_with_arguments(
499 &PHP_RAPHF_G->persistent_handle.hash TSRMLS_CC,
500 php_persistent_handle_apply_cleanup_all, 2, ident_str,
501 ident_len);
502 }
503 }
504
505 HashTable *php_persistent_handle_statall(HashTable *ht TSRMLS_DC)
506 {
507 if (zend_hash_num_elements(&PHP_RAPHF_G->persistent_handle.hash)) {
508 if (!ht) {
509 ALLOC_HASHTABLE(ht);
510 zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
511 }
512 zend_hash_apply_with_arguments(
513 &PHP_RAPHF_G->persistent_handle.hash TSRMLS_CC,
514 php_persistent_handle_apply_statall, 1, ht);
515 } else if (ht) {
516 ht = NULL;
517 }
518
519 return ht;
520 }
521
522 static php_resource_factory_ops_t php_persistent_handle_resource_factory_ops = {
523 (php_resource_factory_handle_ctor_t) php_persistent_handle_acquire,
524 (php_resource_factory_handle_copy_t) php_persistent_handle_accrete,
525 (php_resource_factory_handle_dtor_t) php_persistent_handle_release
526 };
527
528 php_resource_factory_ops_t *php_persistent_handle_get_resource_factory_ops(void)
529 {
530 return &php_persistent_handle_resource_factory_ops;
531 }
532
533 ZEND_BEGIN_ARG_INFO_EX(ai_raphf_stat_persistent_handles, 0, 0, 0)
534 ZEND_END_ARG_INFO();
535 static PHP_FUNCTION(raphf_stat_persistent_handles)
536 {
537 if (SUCCESS == zend_parse_parameters_none()) {
538 object_init(return_value);
539 if (php_persistent_handle_statall(HASH_OF(return_value) TSRMLS_CC)) {
540 return;
541 }
542 zval_dtor(return_value);
543 }
544 RETURN_FALSE;
545 }
546
547 ZEND_BEGIN_ARG_INFO_EX(ai_raphf_clean_persistent_handles, 0, 0, 0)
548 ZEND_ARG_INFO(0, name)
549 ZEND_ARG_INFO(0, ident)
550 ZEND_END_ARG_INFO();
551 static PHP_FUNCTION(raphf_clean_persistent_handles)
552 {
553 char *name_str = NULL, *ident_str = NULL;
554 int name_len = 0, ident_len = 0;
555
556 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!",
557 &name_str, &name_len, &ident_str, &ident_len)) {
558 php_persistent_handle_cleanup(name_str, name_len, ident_str,
559 ident_len TSRMLS_CC);
560 }
561 }
562
563 static const zend_function_entry raphf_functions[] = {
564 ZEND_NS_FENTRY("raphf", stat_persistent_handles,
565 ZEND_FN(raphf_stat_persistent_handles),
566 ai_raphf_stat_persistent_handles, 0)
567 ZEND_NS_FENTRY("raphf", clean_persistent_handles,
568 ZEND_FN(raphf_clean_persistent_handles),
569 ai_raphf_clean_persistent_handles, 0)
570 {0}
571 };
572
573 PHP_INI_BEGIN()
574 STD_PHP_INI_ENTRY("raphf.persistent_handle.limit", "-1", PHP_INI_SYSTEM,
575 OnUpdateLong, persistent_handle.limit, zend_raphf_globals,
576 raphf_globals)
577 PHP_INI_END()
578
579 static HashTable *php_persistent_handles_global_hash;
580
581 static PHP_GINIT_FUNCTION(raphf)
582 {
583 raphf_globals->persistent_handle.limit = -1;
584
585 zend_hash_init(&raphf_globals->persistent_handle.hash, 0, NULL,
586 php_persistent_handle_hash_dtor, 1);
587 if (php_persistent_handles_global_hash) {
588 zend_hash_copy(&raphf_globals->persistent_handle.hash,
589 php_persistent_handles_global_hash, NULL, NULL,
590 sizeof(php_persistent_handle_provider_t));
591 }
592 }
593
594 static PHP_GSHUTDOWN_FUNCTION(raphf)
595 {
596 zend_hash_destroy(&raphf_globals->persistent_handle.hash);
597 }
598
599 PHP_MINIT_FUNCTION(raphf)
600 {
601 php_persistent_handles_global_hash = &PHP_RAPHF_G->persistent_handle.hash;
602 REGISTER_INI_ENTRIES();
603 return SUCCESS;
604 }
605
606 PHP_MSHUTDOWN_FUNCTION(raphf)
607 {
608 UNREGISTER_INI_ENTRIES();
609 php_persistent_handles_global_hash = NULL;
610 return SUCCESS;
611 }
612
613 static int php_persistent_handle_apply_info_ex(void *p TSRMLS_DC, int argc,
614 va_list argv, zend_hash_key *key)
615 {
616 php_persistent_handle_list_t **list = p;
617 zend_hash_key *super_key = va_arg(argv, zend_hash_key *);
618 char used[21], free[21];
619
620 slprintf(used, sizeof(used), "%u", (*list)->used);
621 slprintf(free, sizeof(free), "%d", zend_hash_num_elements(&(*list)->free));
622
623 php_info_print_table_row(4, super_key->arKey, key->arKey, used, free);
624
625 return ZEND_HASH_APPLY_KEEP;
626 }
627
628 static int php_persistent_handle_apply_info(void *p TSRMLS_DC, int argc,
629 va_list argv, zend_hash_key *key)
630 {
631 php_persistent_handle_provider_t *provider = p;
632
633 zend_hash_apply_with_arguments(&provider->list.free TSRMLS_CC,
634 php_persistent_handle_apply_info_ex, 1, key);
635
636 return ZEND_HASH_APPLY_KEEP;
637 }
638
639 PHP_MINFO_FUNCTION(raphf)
640 {
641 php_info_print_table_start();
642 php_info_print_table_header(2,
643 "Resource and persistent handle factory support", "enabled");
644 php_info_print_table_row(2, "Extension version", PHP_RAPHF_VERSION);
645 php_info_print_table_end();
646
647 php_info_print_table_start();
648 php_info_print_table_colspan_header(4, "Persistent handles in this "
649 #ifdef ZTS
650 "thread"
651 #else
652 "process"
653 #endif
654 );
655 php_info_print_table_header(4, "Provider", "Ident", "Used", "Free");
656 zend_hash_apply_with_arguments(
657 &PHP_RAPHF_G->persistent_handle.hash TSRMLS_CC,
658 php_persistent_handle_apply_info, 0);
659 php_info_print_table_end();
660
661 DISPLAY_INI_ENTRIES();
662 }
663
664 zend_module_entry raphf_module_entry = {
665 STANDARD_MODULE_HEADER,
666 "raphf",
667 raphf_functions,
668 PHP_MINIT(raphf),
669 PHP_MSHUTDOWN(raphf),
670 NULL,
671 NULL,
672 PHP_MINFO(raphf),
673 PHP_RAPHF_VERSION,
674 ZEND_MODULE_GLOBALS(raphf),
675 PHP_GINIT(raphf),
676 PHP_GSHUTDOWN(raphf),
677 NULL,
678 STANDARD_MODULE_PROPERTIES_EX
679 };
680 /* }}} */
681
682 #ifdef COMPILE_DL_RAPHF
683 ZEND_GET_MODULE(raphf)
684 #endif
685
686
687 /*
688 * Local variables:
689 * tab-width: 4
690 * c-basic-offset: 4
691 * End:
692 * vim600: noet sw=4 ts=4 fdm=marker
693 * vim<600: noet sw=4 ts=4
694 */